Migrate to webdriverio
This commit is contained in:
parent
2a4c9669d2
commit
3419e0e1fe
|
@ -22,6 +22,8 @@
|
||||||
"plugin:@angular-eslint/template/process-inline-templates"
|
"plugin:@angular-eslint/template/process-inline-templates"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"jsdoc/newline-after-description": "off",
|
||||||
|
"jsdoc/check-alignment": "off",
|
||||||
"lines-between-class-members": "off",
|
"lines-between-class-members": "off",
|
||||||
"@typescript-eslint/lines-between-class-members": [ "off" ],
|
"@typescript-eslint/lines-between-class-members": [ "off" ],
|
||||||
"arrow-body-style": "off",
|
"arrow-body-style": "off",
|
||||||
|
|
|
@ -8,3 +8,4 @@
|
||||||
/src/locale/target/iso639_*.xml
|
/src/locale/target/iso639_*.xml
|
||||||
/src/locale/target/player_*.xml
|
/src/locale/target/player_*.xml
|
||||||
/src/locale/target/server_*.xml
|
/src/locale/target/server_*.xml
|
||||||
|
/e2e/local.log
|
||||||
|
|
|
@ -233,21 +233,6 @@
|
||||||
"with": "src/environments/environment.hmr.ts"
|
"with": "src/environments/environment.hmr.ts"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"e2e": {
|
|
||||||
"localize": false,
|
|
||||||
"budgets": [
|
|
||||||
{
|
|
||||||
"type": "anyComponentStyle",
|
|
||||||
"maximumWarning": "6kb"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fileReplacements": [
|
|
||||||
{
|
|
||||||
"replace": "src/environments/environment.ts",
|
|
||||||
"with": "src/environments/environment.e2e.ts"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -266,10 +251,6 @@
|
||||||
},
|
},
|
||||||
"ar-locale": {
|
"ar-locale": {
|
||||||
"browserTarget": "PeerTube:build:ar-locale"
|
"browserTarget": "PeerTube:build:ar-locale"
|
||||||
},
|
|
||||||
"e2e": {
|
|
||||||
"browserTarget": "PeerTube:build:e2e",
|
|
||||||
"proxyConfig": "e2e/proxy.config.json"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -361,25 +342,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"PeerTube-e2e": {
|
|
||||||
"root": "e2e/",
|
|
||||||
"sourceRoot": "",
|
|
||||||
"projectType": "application",
|
|
||||||
"architect": {
|
|
||||||
"e2e": {
|
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
|
||||||
"options": {
|
|
||||||
"protractorConfig": "e2e/protractor.conf.js",
|
|
||||||
"devServerTarget": "PeerTube:serve:e2e"
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"local": {
|
|
||||||
"protractorConfig": "e2e/local-protractor.conf.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultProject": "PeerTube",
|
"defaultProject": "PeerTube",
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
// Protractor configuration file, see link for more information
|
|
||||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
|
||||||
|
|
||||||
const {SpecReporter} = require('jasmine-spec-reporter')
|
|
||||||
|
|
||||||
exports.config = {
|
|
||||||
allScriptsTimeout: 25000,
|
|
||||||
specs: ['./src/**/*.e2e-spec.ts'],
|
|
||||||
|
|
||||||
directConnect: true,
|
|
||||||
|
|
||||||
multiCapabilities: [
|
|
||||||
{
|
|
||||||
'browserName': 'firefox',
|
|
||||||
'name': 'Firefox',
|
|
||||||
'moz:firefoxOptions': {
|
|
||||||
binary: '/usr/bin/firefox-developer-edition',
|
|
||||||
// args: ["-headless"],
|
|
||||||
log: {
|
|
||||||
"level": "info" // default is "info"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'browserName': 'firefox',
|
|
||||||
'name': 'Firefox ESR',
|
|
||||||
'moz:firefoxOptions': {
|
|
||||||
binary: '/usr/bin/firefox-esr',
|
|
||||||
// args: ["-headless"],
|
|
||||||
log: {
|
|
||||||
"level": "info" // default is "info"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'browserName': 'chrome',
|
|
||||||
'name': 'Chromium'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
maxSessions: 1,
|
|
||||||
baseUrl: 'http://localhost:3000/',
|
|
||||||
framework: 'jasmine',
|
|
||||||
jasmineNodeOpts: {
|
|
||||||
showColors: true,
|
|
||||||
defaultTimeoutInterval: 45000,
|
|
||||||
print: function() {}
|
|
||||||
},
|
|
||||||
|
|
||||||
onPrepare() {
|
|
||||||
require('ts-node').register({
|
|
||||||
project: require('path').join(__dirname, './tsconfig.json')
|
|
||||||
})
|
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
// Protractor configuration file, see link for more information
|
|
||||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
|
||||||
|
|
||||||
const {SpecReporter} = require('jasmine-spec-reporter')
|
|
||||||
|
|
||||||
exports.config = {
|
|
||||||
allScriptsTimeout: 25000,
|
|
||||||
specs: [ './src/**/*.e2e-spec.ts' ],
|
|
||||||
|
|
||||||
seleniumAddress: 'http://hub-cloud.browserstack.com/wd/hub',
|
|
||||||
commonCapabilities: {
|
|
||||||
'browserstack.user': process.env.BROWSERSTACK_USER,
|
|
||||||
'browserstack.key': process.env.BROWSERSTACK_KEY,
|
|
||||||
'browserstack.local': true,
|
|
||||||
'browserstack.console': 'verbose',
|
|
||||||
'browserstack.networkLogs': true,
|
|
||||||
'browserstack.debug': true,
|
|
||||||
project: 'PeerTube',
|
|
||||||
build: 'Main',
|
|
||||||
name: 'Bstack-[Protractor] Parallel Test'
|
|
||||||
},
|
|
||||||
|
|
||||||
multiCapabilities: [
|
|
||||||
{
|
|
||||||
browserName: 'Safari',
|
|
||||||
version: '11.1',
|
|
||||||
name: 'Safari Desktop',
|
|
||||||
resolution: '1280x1024'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Chrome',
|
|
||||||
name: 'Latest Chrome Desktop',
|
|
||||||
resolution: '1280x1024'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Firefox',
|
|
||||||
version: '68', // ESR
|
|
||||||
name: 'Firefox ESR Desktop',
|
|
||||||
resolution: '1280x1024'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Firefox',
|
|
||||||
name: 'Latest Firefox Desktop',
|
|
||||||
resolution: '1280x1024'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Edge',
|
|
||||||
name: 'Latest Edge Desktop',
|
|
||||||
resolution: '1280x1024'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Chrome',
|
|
||||||
device: 'Google Nexus 6',
|
|
||||||
real_mobile: 'true',
|
|
||||||
os_version: '5.0',
|
|
||||||
name: 'Latest Chrome Android'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Safari',
|
|
||||||
device: 'iPhone 8 Plus',
|
|
||||||
real_mobile: 'true',
|
|
||||||
os_version: '11',
|
|
||||||
name: 'Safari iPhone'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'Safari',
|
|
||||||
device: 'iPad 7th',
|
|
||||||
real_mobile: 'true',
|
|
||||||
os_version: '13',
|
|
||||||
name: 'Safari iPad'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// maxSessions: 1,
|
|
||||||
// BrowserStack compatible ports: https://www.browserstack.com/question/664
|
|
||||||
baseUrl: 'http://localhost:3333/',
|
|
||||||
framework: 'jasmine',
|
|
||||||
jasmineNodeOpts: {
|
|
||||||
showColors: true,
|
|
||||||
defaultTimeoutInterval: 45000,
|
|
||||||
print: function() {}
|
|
||||||
},
|
|
||||||
|
|
||||||
onPrepare() {
|
|
||||||
require('ts-node').register({
|
|
||||||
project: require('path').join(__dirname, './tsconfig.json')
|
|
||||||
})
|
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({
|
|
||||||
spec: { displayStacktrace: 'raw' }
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.config.multiCapabilities.forEach(function (caps) {
|
|
||||||
for (var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i]
|
|
||||||
})
|
|
|
@ -1,37 +0,0 @@
|
||||||
{
|
|
||||||
"/api": {
|
|
||||||
"target": "http://localhost:9000",
|
|
||||||
"secure": false
|
|
||||||
},
|
|
||||||
"/plugins": {
|
|
||||||
"target": "http://localhost:9000",
|
|
||||||
"secure": false
|
|
||||||
},
|
|
||||||
"/themes": {
|
|
||||||
"target": "http://localhost:9000",
|
|
||||||
"secure": false
|
|
||||||
},
|
|
||||||
"/static": {
|
|
||||||
"target": "http://localhost:9000",
|
|
||||||
"secure": false
|
|
||||||
},
|
|
||||||
"/lazy-static": {
|
|
||||||
"target": "http://localhost:9000",
|
|
||||||
"secure": false
|
|
||||||
},
|
|
||||||
"/socket.io": {
|
|
||||||
"target": "ws://localhost:9000",
|
|
||||||
"secure": false,
|
|
||||||
"ws": true
|
|
||||||
},
|
|
||||||
"/!(client)**": {
|
|
||||||
"target": "http://localhost:3333/client/index.html",
|
|
||||||
"secure": false,
|
|
||||||
"logLevel": "debug"
|
|
||||||
},
|
|
||||||
"/!(client)**/**": {
|
|
||||||
"target": "http://localhost:3333/client/index.html",
|
|
||||||
"secure": false,
|
|
||||||
"logLevel": "debug"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
browser.addCommand('chooseFile', async function (this: WebdriverIO.Element, localFilePath: string) {
|
||||||
|
try {
|
||||||
|
const remoteFile = await browser.uploadFile(localFilePath)
|
||||||
|
|
||||||
|
return this.addValue(remoteFile)
|
||||||
|
} catch {
|
||||||
|
console.log('Cannot upload file, fallback to add value.')
|
||||||
|
|
||||||
|
// Firefox does not support upload file, but if we're running the test in local we don't really need it
|
||||||
|
return this.addValue(localFilePath)
|
||||||
|
}
|
||||||
|
}, true)
|
|
@ -1,23 +1,25 @@
|
||||||
import { browser, element, by } from 'protractor'
|
import { go } from '../utils'
|
||||||
|
|
||||||
export class LoginPage {
|
export class LoginPage {
|
||||||
async loginAsRootUser () {
|
async loginAsRootUser () {
|
||||||
await browser.get('/login')
|
await go('/login')
|
||||||
|
|
||||||
await browser.executeScript(`window.localStorage.setItem('no_instance_config_warning_modal', 'true')`)
|
await browser.execute(`window.localStorage.setItem('no_instance_config_warning_modal', 'true')`)
|
||||||
await browser.executeScript(`window.localStorage.setItem('no_welcome_modal', 'true')`)
|
await browser.execute(`window.localStorage.setItem('no_welcome_modal', 'true')`)
|
||||||
|
|
||||||
element(by.css('input#username')).sendKeys('root')
|
await $('input#username').setValue('root')
|
||||||
element(by.css('input#password')).sendKeys('test1')
|
await $('input#password').setValue('test1')
|
||||||
|
|
||||||
await browser.sleep(1000)
|
await browser.pause(1000)
|
||||||
|
|
||||||
await element(by.css('form input[type=submit]')).click()
|
await $('form input[type=submit]').click()
|
||||||
|
|
||||||
expect(this.getLoggedInInfo().getText()).toContain('root')
|
await this.getLoggedInInfoElem().waitForExist()
|
||||||
|
|
||||||
|
await expect(this.getLoggedInInfoElem()).toHaveText('root')
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLoggedInInfo () {
|
private getLoggedInInfoElem () {
|
||||||
return element(by.css('.logged-in-display-name'))
|
return $('.logged-in-display-name')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +1,117 @@
|
||||||
import { by, element, browser } from 'protractor'
|
import { go } from '../utils'
|
||||||
|
|
||||||
export class MyAccountPage {
|
export class MyAccountPage {
|
||||||
|
|
||||||
navigateToMyVideos () {
|
navigateToMyVideos () {
|
||||||
return element(by.css('a[href="/my-library/videos"]')).click()
|
return $('a[href="/my-library/videos"]').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateToMyPlaylists () {
|
navigateToMyPlaylists () {
|
||||||
return element(by.css('a[href="/my-library/video-playlists"]')).click()
|
return $('a[href="/my-library/video-playlists"]').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateToMyHistory () {
|
navigateToMyHistory () {
|
||||||
return element(by.css('a[href="/my-library/history/videos"]')).click()
|
return $('a[href="/my-library/history/videos"]').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
// My account Videos
|
// My account Videos
|
||||||
|
|
||||||
async removeVideo (name: string) {
|
async removeVideo (name: string) {
|
||||||
const container = this.getVideoElement(name)
|
const container = await this.getVideoElement(name)
|
||||||
|
|
||||||
await container.element(by.css('.dropdown-toggle')).click()
|
await container.$('.dropdown-toggle').click()
|
||||||
|
|
||||||
const dropdownMenu = container.element(by.css('.dropdown-menu .dropdown-item:nth-child(2)'))
|
const dropdownMenu = () => container.$('.dropdown-menu .dropdown-item:nth-child(2)')
|
||||||
await browser.wait(browser.ExpectedConditions.presenceOf(dropdownMenu))
|
|
||||||
|
|
||||||
return dropdownMenu.click()
|
await dropdownMenu().waitForDisplayed()
|
||||||
|
return dropdownMenu().click()
|
||||||
}
|
}
|
||||||
|
|
||||||
validRemove () {
|
validRemove () {
|
||||||
return element(by.css('input[type=submit]')).click()
|
return $('input[type=submit]').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
countVideos (names: string[]) {
|
async countVideos (names: string[]) {
|
||||||
return element.all(by.css('.video'))
|
const elements = await $$('.video').filter(async e => {
|
||||||
.filter(e => {
|
const t = await e.$('.video-miniature-name').getText()
|
||||||
return e.element(by.css('.video-miniature-name'))
|
|
||||||
.getText()
|
return names.some(n => t.includes(n))
|
||||||
.then(t => names.some(n => t.includes(n)))
|
})
|
||||||
})
|
|
||||||
.count()
|
return elements.length
|
||||||
}
|
}
|
||||||
|
|
||||||
// My account playlists
|
// My account playlists
|
||||||
|
|
||||||
getPlaylistVideosText (name: string) {
|
async getPlaylistVideosText (name: string) {
|
||||||
return this.getPlaylist(name).element(by.css('.miniature-playlist-info-overlay')).getText()
|
const elem = await this.getPlaylist(name)
|
||||||
|
|
||||||
|
return elem.$('.miniature-playlist-info-overlay').getText()
|
||||||
}
|
}
|
||||||
|
|
||||||
clickOnPlaylist (name: string) {
|
async clickOnPlaylist (name: string) {
|
||||||
return this.getPlaylist(name).element(by.css('.miniature-thumbnail')).click()
|
const elem = await this.getPlaylist(name)
|
||||||
|
|
||||||
|
return elem.$('.miniature-thumbnail').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
countTotalPlaylistElements () {
|
async countTotalPlaylistElements () {
|
||||||
return element.all(by.css('my-video-playlist-element-miniature')).count()
|
await $('<my-video-playlist-element-miniature>').waitForDisplayed()
|
||||||
|
|
||||||
|
return $$('<my-video-playlist-element-miniature>').length
|
||||||
}
|
}
|
||||||
|
|
||||||
playPlaylist () {
|
playPlaylist () {
|
||||||
return element(by.css('.playlist-info .miniature-thumbnail')).click()
|
return $('.playlist-info .miniature-thumbnail').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async goOnAssociatedPlaylistEmbed () {
|
async goOnAssociatedPlaylistEmbed () {
|
||||||
let url = await browser.getCurrentUrl()
|
let url = await browser.getUrl()
|
||||||
url = url.replace('/w/p/', '/video-playlists/embed/')
|
url = url.replace('/w/p/', '/video-playlists/embed/')
|
||||||
url = url.replace(':3333', ':9001')
|
url = url.replace(':3333', ':9001')
|
||||||
|
|
||||||
return browser.get(url)
|
return go(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// My account Videos
|
// My account Videos
|
||||||
|
|
||||||
private getVideoElement (name: string) {
|
private async getVideoElement (name: string) {
|
||||||
return element.all(by.css('.video'))
|
const video = async () => {
|
||||||
.filter(e => e.element(by.css('.video-miniature-name')).getText().then(t => t.includes(name)))
|
const videos = await $$('.video').filter(async e => {
|
||||||
.first()
|
const t = await e.$('.video-miniature-name').getText()
|
||||||
|
|
||||||
|
return t.includes(name)
|
||||||
|
})
|
||||||
|
|
||||||
|
return videos[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
await browser.waitUntil(async () => {
|
||||||
|
return (await video()).isDisplayed()
|
||||||
|
})
|
||||||
|
|
||||||
|
return video()
|
||||||
}
|
}
|
||||||
|
|
||||||
// My account playlists
|
// My account playlists
|
||||||
|
|
||||||
private getPlaylist (name: string) {
|
private async getPlaylist (name: string) {
|
||||||
return element.all(by.css('my-video-playlist-miniature'))
|
const playlist = () => {
|
||||||
.filter(e => e.element(by.css('.miniature-name')).getText().then(t => t.includes(name)))
|
return $$('my-video-playlist-miniature')
|
||||||
.first()
|
.filter(async e => {
|
||||||
|
const t = await e.$('.miniature-name').getText()
|
||||||
|
|
||||||
|
return t.includes(name)
|
||||||
|
})
|
||||||
|
.then(elems => elems[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
await browser.waitUntil(async () => {
|
||||||
|
const el = await playlist()
|
||||||
|
|
||||||
|
return el?.isDisplayed()
|
||||||
|
})
|
||||||
|
|
||||||
|
return playlist()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,54 @@
|
||||||
import { browser, by, element } from 'protractor'
|
|
||||||
import { browserSleep, isIOS, isMobileDevice, isSafari } from '../utils'
|
import { browserSleep, isIOS, isMobileDevice, isSafari } from '../utils'
|
||||||
|
|
||||||
export class PlayerPage {
|
export class PlayerPage {
|
||||||
|
|
||||||
async getWatchVideoPlayerCurrentTime () {
|
getWatchVideoPlayerCurrentTime () {
|
||||||
const elem = element(by.css('video'))
|
const elem = $('video')
|
||||||
|
|
||||||
return elem.getAttribute('currentTime')
|
if (isIOS()) {
|
||||||
|
return elem.getAttribute('currentTime')
|
||||||
|
.then(t => parseInt(t, 10))
|
||||||
|
.then(t => Math.round(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem.getProperty('currentTime')
|
||||||
}
|
}
|
||||||
|
|
||||||
waitUntilPlaylistInfo (text: string) {
|
waitUntilPlaylistInfo (text: string, maxTime: number) {
|
||||||
const elem = element(by.css('.video-js .vjs-playlist-info'))
|
return browser.waitUntil(async () => {
|
||||||
|
return (await $('.video-js .vjs-playlist-info').getText()).includes(text)
|
||||||
return browser.wait(browser.ExpectedConditions.textToBePresentInElement(elem, text))
|
}, { timeout: maxTime })
|
||||||
}
|
}
|
||||||
|
|
||||||
waitUntilPlayerWrapper () {
|
waitUntilPlayerWrapper () {
|
||||||
const elem = element(by.css('#placeholder-preview'))
|
return browser.waitUntil(async () => {
|
||||||
|
return !!(await $('#placeholder-preview'))
|
||||||
return browser.wait(browser.ExpectedConditions.presenceOf(elem))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async playAndPauseVideo (isAutoplay: boolean) {
|
async playAndPauseVideo (isAutoplay: boolean) {
|
||||||
const videojsEl = element(by.css('div.video-js'))
|
const videojsElem = () => $('div.video-js')
|
||||||
await browser.wait(browser.ExpectedConditions.elementToBeClickable(videojsEl))
|
|
||||||
|
await videojsElem().waitForExist()
|
||||||
|
|
||||||
// Autoplay is disabled on iOS and Safari
|
// Autoplay is disabled on iOS and Safari
|
||||||
if (await isIOS() || await isSafari() || await isMobileDevice()) {
|
if (isIOS() || isSafari() || isMobileDevice()) {
|
||||||
// We can't play the video using protractor if it is not muted
|
// We can't play the video using protractor if it is not muted
|
||||||
await browser.executeScript(`document.querySelector('video').muted = true`)
|
await browser.execute(`document.querySelector('video').muted = true`)
|
||||||
await this.clickOnPlayButton()
|
await this.clickOnPlayButton()
|
||||||
} else if (isAutoplay === false) {
|
} else if (isAutoplay === false) {
|
||||||
await this.clickOnPlayButton()
|
await this.clickOnPlayButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
await browserSleep(2000)
|
await browserSleep(2000)
|
||||||
await browser.wait(browser.ExpectedConditions.invisibilityOf(element(by.css('.vjs-loading-spinner'))))
|
|
||||||
|
|
||||||
await browserSleep(2000)
|
await browser.waitUntil(async () => {
|
||||||
|
return !await $('.vjs-loading-spinner').isDisplayedInViewport()
|
||||||
|
}, { timeout: 20 * 1000 })
|
||||||
|
|
||||||
await videojsEl.click()
|
await browserSleep(4000)
|
||||||
|
|
||||||
|
await videojsElem().click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async playVideo () {
|
async playVideo () {
|
||||||
|
@ -47,8 +56,9 @@ export class PlayerPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async clickOnPlayButton () {
|
private async clickOnPlayButton () {
|
||||||
const playButton = element(by.css('.vjs-big-play-button'))
|
const playButton = () => $('.vjs-big-play-button')
|
||||||
await browser.wait(browser.ExpectedConditions.elementToBeClickable(playButton))
|
|
||||||
await playButton.click()
|
await playButton().waitForClickable()
|
||||||
|
await playButton().click()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { by, element } from 'protractor'
|
|
||||||
|
|
||||||
export class VideoUpdatePage {
|
export class VideoUpdatePage {
|
||||||
|
|
||||||
async updateName (videoName: string) {
|
async updateName (videoName: string) {
|
||||||
const nameInput = element(by.css('input#name'))
|
const nameInput = $('input#name')
|
||||||
await nameInput.clear()
|
|
||||||
await nameInput.sendKeys(videoName)
|
await nameInput.waitForDisplayed()
|
||||||
|
await nameInput.clearValue()
|
||||||
|
await nameInput.setValue(videoName)
|
||||||
}
|
}
|
||||||
|
|
||||||
async validUpdate () {
|
async validUpdate () {
|
||||||
|
@ -15,6 +15,6 @@ export class VideoUpdatePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSubmitButton () {
|
private getSubmitButton () {
|
||||||
return element(by.css('.submit-container .action-button'))
|
return $('.submit-container .action-button')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
import { browser, by, element } from 'protractor'
|
|
||||||
import { FileDetector } from 'selenium-webdriver/remote'
|
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
export class VideoUploadPage {
|
export class VideoUploadPage {
|
||||||
async navigateTo () {
|
async navigateTo () {
|
||||||
await element(by.css('.header .publish-button')).click()
|
await $('.header .publish-button').click()
|
||||||
|
|
||||||
return browser.wait(browser.ExpectedConditions.visibilityOf(element(by.css('.upload-video-container'))))
|
await $('.upload-video-container').waitForDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadVideo () {
|
async uploadVideo () {
|
||||||
browser.setFileDetector(new FileDetector())
|
|
||||||
|
|
||||||
const fileToUpload = join(__dirname, '../../fixtures/video.mp4')
|
const fileToUpload = join(__dirname, '../../fixtures/video.mp4')
|
||||||
const fileInputSelector = '.upload-video-container input[type=file]'
|
const fileInputSelector = '.upload-video-container input[type=file]'
|
||||||
const parentFileInput = '.upload-video-container .button-file'
|
const parentFileInput = '.upload-video-container .button-file'
|
||||||
|
|
||||||
// Avoid sending keys on non visible element
|
// Avoid sending keys on non visible element
|
||||||
await browser.executeScript(`document.querySelector('${fileInputSelector}').style.opacity = 1`)
|
await browser.execute(`document.querySelector('${fileInputSelector}').style.opacity = 1`)
|
||||||
await browser.executeScript(`document.querySelector('${parentFileInput}').style.overflow = 'initial'`)
|
await browser.execute(`document.querySelector('${parentFileInput}').style.overflow = 'initial'`)
|
||||||
|
|
||||||
await browser.sleep(1000)
|
await browser.pause(1000)
|
||||||
|
|
||||||
const elem = element(by.css(fileInputSelector))
|
const elem = await $(fileInputSelector)
|
||||||
await elem.sendKeys(fileToUpload)
|
await elem.chooseFile(fileToUpload)
|
||||||
|
|
||||||
// Wait for the upload to finish
|
// Wait for the upload to finish
|
||||||
await browser.wait(async () => {
|
await browser.waitUntil(async () => {
|
||||||
const actionButton = this.getSecondStepSubmitButton().element(by.css('.action-button'))
|
const actionButton = this.getSecondStepSubmitButton().$('.action-button')
|
||||||
|
|
||||||
const klass = await actionButton.getAttribute('class')
|
const klass = await actionButton.getAttribute('class')
|
||||||
return !klass.includes('disabled')
|
return !klass.includes('disabled')
|
||||||
|
@ -35,16 +31,18 @@ export class VideoUploadPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
async validSecondUploadStep (videoName: string) {
|
async validSecondUploadStep (videoName: string) {
|
||||||
const nameInput = element(by.css('input#name'))
|
const nameInput = $('input#name')
|
||||||
await nameInput.clear()
|
await nameInput.clearValue()
|
||||||
await nameInput.sendKeys(videoName)
|
await nameInput.setValue(videoName)
|
||||||
|
|
||||||
await this.getSecondStepSubmitButton().click()
|
await this.getSecondStepSubmitButton().click()
|
||||||
|
|
||||||
return browser.wait(browser.ExpectedConditions.urlContains('/w/'))
|
return browser.waitUntil(async () => {
|
||||||
|
return (await browser.getUrl()).includes('/w/')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private getSecondStepSubmitButton () {
|
private getSecondStepSubmitButton () {
|
||||||
return element(by.css('.submit-container my-button'))
|
return $('.submit-container my-button')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { browser, by, element, ElementFinder, ExpectedConditions } from 'protractor'
|
import { browserSleep, go } from '../utils'
|
||||||
import { browserSleep, isMobileDevice } from '../utils'
|
|
||||||
|
|
||||||
export class VideoWatchPage {
|
export class VideoWatchPage {
|
||||||
async goOnVideosList (isMobileDevice: boolean, isSafari: boolean) {
|
async goOnVideosList (isMobileDevice: boolean, isSafari: boolean) {
|
||||||
|
@ -12,19 +11,19 @@ export class VideoWatchPage {
|
||||||
url = '/videos/recently-added'
|
url = '/videos/recently-added'
|
||||||
}
|
}
|
||||||
|
|
||||||
await browser.get(url, 20000)
|
await go(url)
|
||||||
|
|
||||||
// Waiting the following element does not work on Safari...
|
// Waiting the following element does not work on Safari...
|
||||||
if (isSafari) return browserSleep(3000)
|
if (isSafari) return browserSleep(3000)
|
||||||
|
|
||||||
const elem = element.all(by.css('.videos .video-miniature .video-miniature-name')).first()
|
await $('.videos .video-miniature .video-miniature-name').waitForDisplayed()
|
||||||
return browser.wait(browser.ExpectedConditions.visibilityOf(elem))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideosListName () {
|
async getVideosListName () {
|
||||||
return element.all(by.css('.videos .video-miniature .video-miniature-name'))
|
const elems = await $$('.videos .video-miniature .video-miniature-name')
|
||||||
.getText()
|
const texts = await Promise.all(elems.map(e => e.getText()))
|
||||||
.then((texts: any) => texts.map((t: any) => t.trim()))
|
|
||||||
|
return texts.map(t => t.trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
waitWatchVideoName (videoName: string, isMobileDevice: boolean, isSafari: boolean) {
|
waitWatchVideoName (videoName: string, isMobileDevice: boolean, isSafari: boolean) {
|
||||||
|
@ -33,99 +32,134 @@ export class VideoWatchPage {
|
||||||
// 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 = isMobileDevice ? 0 : 1
|
||||||
|
|
||||||
const elem = element.all(by.css('.video-info .video-info-name')).get(index)
|
return browser.waitUntil(async () => {
|
||||||
return browser.wait(browser.ExpectedConditions.textToBePresentInElement(elem, videoName))
|
return (await $$('.video-info .video-info-name')[index].getText()).includes(videoName)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideoName () {
|
getVideoName () {
|
||||||
return this.getVideoNameElement().getText()
|
return this.getVideoNameElement().then(e => e.getText())
|
||||||
}
|
}
|
||||||
|
|
||||||
async goOnAssociatedEmbed () {
|
async goOnAssociatedEmbed () {
|
||||||
let url = await browser.getCurrentUrl()
|
let url = await browser.getUrl()
|
||||||
url = url.replace('/w/', '/videos/embed/')
|
url = url.replace('/w/', '/videos/embed/')
|
||||||
url = url.replace(':3333', ':9001')
|
url = url.replace(':3333', ':9001')
|
||||||
|
|
||||||
return browser.get(url)
|
return go(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
async goOnP2PMediaLoaderEmbed () {
|
goOnP2PMediaLoaderEmbed () {
|
||||||
return browser.get('https://peertube2.cpy.re/videos/embed/969bf103-7818-43b5-94a0-de159e13de50')
|
return go(
|
||||||
|
'https://peertube2.cpy.re/videos/embed/969bf103-7818-43b5-94a0-de159e13de50'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async goOnP2PMediaLoaderPlaylistEmbed () {
|
goOnP2PMediaLoaderPlaylistEmbed () {
|
||||||
return browser.get('https://peertube2.cpy.re/video-playlists/embed/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a')
|
return go(
|
||||||
|
'https://peertube2.cpy.re/video-playlists/embed/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async clickOnVideo (videoName: string) {
|
async clickOnVideo (videoName: string) {
|
||||||
const video = element.all(by.css('.videos .video-miniature .video-miniature-name'))
|
const video = async () => {
|
||||||
.filter(e => e.getText().then(t => t === videoName ))
|
const videos = await $$('.videos .video-miniature .video-miniature-name').filter(async e => {
|
||||||
.first()
|
const t = await e.getText()
|
||||||
|
|
||||||
await browser.wait(browser.ExpectedConditions.elementToBeClickable(video))
|
return t === videoName
|
||||||
await video.click()
|
})
|
||||||
|
|
||||||
await browser.wait(browser.ExpectedConditions.urlContains('/w/'))
|
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 () {
|
async clickOnFirstVideo () {
|
||||||
const video = element.all(by.css('.videos .video-miniature .video-thumbnail')).first()
|
const video = () => $('.videos .video-miniature .video-thumbnail')
|
||||||
const videoName = element.all(by.css('.videos .video-miniature .video-miniature-name')).first()
|
const videoName = () => $('.videos .video-miniature .video-miniature-name')
|
||||||
|
|
||||||
// Don't know why but the expectation fails on Safari
|
await video().waitForClickable()
|
||||||
await browser.wait(browser.ExpectedConditions.elementToBeClickable(video))
|
|
||||||
|
|
||||||
const textToReturn = videoName.getText()
|
const textToReturn = await videoName().getText()
|
||||||
await video.click()
|
await video().click()
|
||||||
|
|
||||||
|
await browser.waitUntil(async () => (await browser.getUrl()).includes('/w/'))
|
||||||
|
|
||||||
await browser.wait(browser.ExpectedConditions.urlContains('/w/'))
|
|
||||||
return textToReturn
|
return textToReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
async clickOnUpdate () {
|
async clickOnUpdate () {
|
||||||
const dropdown = element(by.css('my-video-actions-dropdown .action-button'))
|
const dropdown = $('my-video-actions-dropdown .action-button')
|
||||||
await dropdown.click()
|
await dropdown.click()
|
||||||
|
|
||||||
const items: ElementFinder[] = await element.all(by.css('.dropdown-menu.show .dropdown-item'))
|
await $('.dropdown-menu.show .dropdown-item').waitForDisplayed()
|
||||||
|
const items = await $$('.dropdown-menu.show .dropdown-item')
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const href = await item.getAttribute('href')
|
const href = await item.getAttribute('href')
|
||||||
|
|
||||||
if (href && href.includes('/update/')) {
|
if (href?.includes('/update/')) {
|
||||||
await item.click()
|
await item.click()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async clickOnSave () {
|
clickOnSave () {
|
||||||
return element(by.css('.action-button-save')).click()
|
return $('.action-button-save').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async createPlaylist (name: string) {
|
async createPlaylist (name: string) {
|
||||||
await element(by.css('.new-playlist-button')).click()
|
const newPlaylistButton = () => $('.new-playlist-button')
|
||||||
|
|
||||||
await element(by.css('#displayName')).sendKeys(name)
|
await newPlaylistButton().waitForClickable()
|
||||||
|
await newPlaylistButton().click()
|
||||||
|
|
||||||
return element(by.css('.new-playlist-block input[type=submit]')).click()
|
const displayName = () => $('#displayName')
|
||||||
|
|
||||||
|
await displayName().waitForDisplayed()
|
||||||
|
await displayName().setValue(name)
|
||||||
|
|
||||||
|
return $('.new-playlist-block input[type=submit]').click()
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveToPlaylist (name: string) {
|
async saveToPlaylist (name: string) {
|
||||||
return element.all(by.css('my-video-add-to-playlist .playlist'))
|
const playlist = () => $('my-video-add-to-playlist').$(`.playlist=${name}`)
|
||||||
.filter(p => p.getText().then(t => t === name))
|
|
||||||
.click()
|
await playlist().waitForDisplayed()
|
||||||
|
|
||||||
|
return playlist().click()
|
||||||
}
|
}
|
||||||
|
|
||||||
waitUntilVideoName (name: string, maxTime: number) {
|
waitUntilVideoName (name: string, maxTime: number) {
|
||||||
const elem = this.getVideoNameElement()
|
return browser.waitUntil(async () => {
|
||||||
|
return (await this.getVideoName()) === name
|
||||||
return browser.wait(ExpectedConditions.textToBePresentInElement(elem, name), maxTime)
|
}, { timeout: maxTime })
|
||||||
}
|
}
|
||||||
|
|
||||||
private getVideoNameElement () {
|
private async getVideoNameElement () {
|
||||||
// We have 2 video info name block, pick the first that is not empty
|
// We have 2 video info name block, pick the first that is not empty
|
||||||
return element.all(by.css('.video-info-first-row .video-info-name'))
|
const elem = async () => {
|
||||||
.filter(e => e.getText().then(t => !!t))
|
const elems = await $$('.video-info-first-row .video-info-name').filter(e => e.isDisplayed())
|
||||||
.first()
|
|
||||||
|
return elems[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
await browser.waitUntil(async () => {
|
||||||
|
const e = await elem()
|
||||||
|
|
||||||
|
return e?.isDisplayed()
|
||||||
|
})
|
||||||
|
|
||||||
|
return elem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
declare namespace WebdriverIO {
|
||||||
|
interface Element {
|
||||||
|
chooseFile: (path: string) => Promise<void>
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,37 @@
|
||||||
import { browser } from 'protractor'
|
|
||||||
|
|
||||||
async function browserSleep (amount: number) {
|
async function browserSleep (amount: number) {
|
||||||
const oldValue = await browser.waitForAngularEnabled()
|
await browser.pause(amount)
|
||||||
|
|
||||||
// iOS does not seem to work with protractor
|
|
||||||
// https://github.com/angular/protractor/issues/2840
|
|
||||||
if (await isIOS()) browser.waitForAngularEnabled(true)
|
|
||||||
|
|
||||||
await browser.sleep(amount)
|
|
||||||
|
|
||||||
if (await isIOS()) browser.waitForAngularEnabled(oldValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isMobileDevice () {
|
function isMobileDevice () {
|
||||||
const caps = await browser.getCapabilities()
|
const platformName = (browser.capabilities['platformName'] || '').toLowerCase()
|
||||||
return caps.get('realMobile') === 'true' || caps.get('realMobile') === true
|
|
||||||
|
return platformName === 'android' || platformName === 'ios'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isSafari () {
|
function isSafari () {
|
||||||
const caps = await browser.getCapabilities()
|
return browser.capabilities['browserName'] &&
|
||||||
return caps.get('browserName') && caps.get('browserName').toLowerCase() === 'safari'
|
browser.capabilities['browserName'].toLowerCase() === 'safari'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isIOS () {
|
function isIOS () {
|
||||||
return await isMobileDevice() && await isSafari()
|
return isMobileDevice() && isSafari()
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
async function go (url: string) {
|
||||||
|
await browser.url(url)
|
||||||
|
|
||||||
|
// Hide notifications that could fail tests when hiding buttons
|
||||||
|
await browser.execute(() => {
|
||||||
|
const style = document.createElement('style')
|
||||||
|
style.innerHTML = 'p-toast { display: none }'
|
||||||
|
document.head.appendChild(style)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
isMobileDevice,
|
isMobileDevice,
|
||||||
isSafari,
|
isSafari,
|
||||||
isIOS,
|
isIOS,
|
||||||
|
go,
|
||||||
browserSleep
|
browserSleep
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { browser } from 'protractor'
|
|
||||||
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 { VideoUpdatePage } from './po/video-update.po'
|
||||||
import { VideoUploadPage } from './po/video-upload.po'
|
import { VideoUploadPage } from './po/video-upload.po'
|
||||||
import { VideoWatchPage } from './po/video-watch.po'
|
import { VideoWatchPage } from './po/video-watch.po'
|
||||||
import { isIOS, isMobileDevice, isSafari } from './utils'
|
import { browserSleep, go, isIOS, isMobileDevice, isSafari } from './utils'
|
||||||
|
|
||||||
async function skipIfUploadNotSupported () {
|
function isUploadUnsupported () {
|
||||||
if (await isMobileDevice() || await isSafari()) {
|
if (isMobileDevice() || isSafari()) {
|
||||||
console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.')
|
console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -24,11 +23,30 @@ describe('Videos workflow', () => {
|
||||||
let loginPage: LoginPage
|
let loginPage: LoginPage
|
||||||
let playerPage: PlayerPage
|
let playerPage: PlayerPage
|
||||||
|
|
||||||
let videoName = new Date().getTime() + ' video'
|
let videoName = Math.random() + ' video'
|
||||||
const video2Name = new Date().getTime() + ' second video'
|
const video2Name = Math.random() + ' second video'
|
||||||
const playlistName = new Date().getTime() + ' playlist'
|
const playlistName = Math.random() + ' playlist'
|
||||||
let videoWatchUrl: string
|
let videoWatchUrl: string
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
if (isIOS()) {
|
||||||
|
console.log('iOS detected')
|
||||||
|
} else if (isMobileDevice()) {
|
||||||
|
console.log('Android detected.')
|
||||||
|
} else if (isSafari()) {
|
||||||
|
console.log('Safari detected.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
|
await browser.waitUntil(async () => {
|
||||||
|
await go('/')
|
||||||
|
await browserSleep(500)
|
||||||
|
|
||||||
|
return $('<my-app>').isDisplayed()
|
||||||
|
}, { timeout: 20 * 1000 })
|
||||||
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
videoWatchPage = new VideoWatchPage()
|
videoWatchPage = new VideoWatchPage()
|
||||||
videoUploadPage = new VideoUploadPage()
|
videoUploadPage = new VideoUploadPage()
|
||||||
|
@ -37,25 +55,13 @@ describe('Videos workflow', () => {
|
||||||
loginPage = new LoginPage()
|
loginPage = new LoginPage()
|
||||||
playerPage = new PlayerPage()
|
playerPage = new PlayerPage()
|
||||||
|
|
||||||
if (await isIOS()) {
|
if (!isMobileDevice()) {
|
||||||
// iOS does not seem to work with protractor
|
await browser.maximizeWindow()
|
||||||
// https://github.com/angular/protractor/issues/2840
|
|
||||||
browser.waitForAngularEnabled(false)
|
|
||||||
|
|
||||||
console.log('iOS detected')
|
|
||||||
} else if (await isMobileDevice()) {
|
|
||||||
console.log('Android detected.')
|
|
||||||
} else if (await isSafari()) {
|
|
||||||
console.log('Safari detected.')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!await isMobileDevice()) {
|
|
||||||
await browser.driver.manage().window().maximize()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should log in', async () => {
|
it('Should log in', async () => {
|
||||||
if (await isMobileDevice() || await isSafari()) {
|
if (isMobileDevice() || isSafari()) {
|
||||||
console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.')
|
console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -64,7 +70,7 @@ describe('Videos workflow', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should upload a video', async () => {
|
it('Should upload a video', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await videoUploadPage.navigateTo()
|
await videoUploadPage.navigateTo()
|
||||||
|
|
||||||
|
@ -73,62 +79,52 @@ describe('Videos workflow', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list videos', async () => {
|
it('Should list videos', async () => {
|
||||||
await videoWatchPage.goOnVideosList(await isMobileDevice(), await isSafari())
|
await videoWatchPage.goOnVideosList(isMobileDevice(), isSafari())
|
||||||
|
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
const videoNames = videoWatchPage.getVideosListName()
|
const videoNames = await videoWatchPage.getVideosListName()
|
||||||
expect(videoNames).toContain(videoName)
|
expect(videoNames).toContain(videoName)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should go on video watch page', async () => {
|
it('Should go on video watch page', async () => {
|
||||||
let videoNameToExcept = videoName
|
let videoNameToExcept = videoName
|
||||||
|
|
||||||
if (await isMobileDevice() || await isSafari()) {
|
if (isMobileDevice() || isSafari()) {
|
||||||
await browser.get('https://peertube2.cpy.re/w/122d093a-1ede-43bd-bd34-59d2931ffc5e')
|
await go('https://peertube2.cpy.re/w/122d093a-1ede-43bd-bd34-59d2931ffc5e')
|
||||||
videoNameToExcept = 'E2E tests'
|
videoNameToExcept = 'E2E tests'
|
||||||
} else {
|
} else {
|
||||||
await videoWatchPage.clickOnVideo(videoName)
|
await videoWatchPage.clickOnVideo(videoName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return videoWatchPage.waitWatchVideoName(videoNameToExcept, await isMobileDevice(), await isSafari())
|
return videoWatchPage.waitWatchVideoName(videoNameToExcept, isMobileDevice(), isSafari())
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should play the video', async () => {
|
it('Should play the video', async () => {
|
||||||
videoWatchUrl = await browser.getCurrentUrl()
|
videoWatchUrl = await browser.getUrl()
|
||||||
|
|
||||||
await playerPage.playAndPauseVideo(true)
|
await playerPage.playAndPauseVideo(true)
|
||||||
expect(playerPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
|
expect(await playerPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should watch the associated embed video', async () => {
|
it('Should watch the associated embed video', async () => {
|
||||||
const oldValue = await browser.waitForAngularEnabled()
|
|
||||||
await browser.waitForAngularEnabled(false)
|
|
||||||
|
|
||||||
await videoWatchPage.goOnAssociatedEmbed()
|
await videoWatchPage.goOnAssociatedEmbed()
|
||||||
|
|
||||||
await playerPage.playAndPauseVideo(false)
|
await playerPage.playAndPauseVideo(false)
|
||||||
expect(playerPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
|
expect(await playerPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
|
||||||
|
|
||||||
await browser.waitForAngularEnabled(oldValue)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should watch the p2p media loader embed video', async () => {
|
it('Should watch the p2p media loader embed video', async () => {
|
||||||
const oldValue = await browser.waitForAngularEnabled()
|
|
||||||
await browser.waitForAngularEnabled(false)
|
|
||||||
|
|
||||||
await videoWatchPage.goOnP2PMediaLoaderEmbed()
|
await videoWatchPage.goOnP2PMediaLoaderEmbed()
|
||||||
|
|
||||||
await playerPage.playAndPauseVideo(false)
|
await playerPage.playAndPauseVideo(false)
|
||||||
expect(playerPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
|
expect(await playerPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
|
||||||
|
|
||||||
await browser.waitForAngularEnabled(oldValue)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should update the video', async () => {
|
it('Should update the video', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await browser.get(videoWatchUrl)
|
await go(videoWatchUrl)
|
||||||
|
|
||||||
await videoWatchPage.clickOnUpdate()
|
await videoWatchPage.clickOnUpdate()
|
||||||
|
|
||||||
|
@ -142,14 +138,14 @@ describe('Videos workflow', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should add the video in my playlist', async () => {
|
it('Should add the video in my playlist', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await videoWatchPage.clickOnSave()
|
await videoWatchPage.clickOnSave()
|
||||||
|
|
||||||
await videoWatchPage.createPlaylist(playlistName)
|
await videoWatchPage.createPlaylist(playlistName)
|
||||||
|
|
||||||
await videoWatchPage.saveToPlaylist(playlistName)
|
await videoWatchPage.saveToPlaylist(playlistName)
|
||||||
await browser.sleep(5000)
|
await browser.pause(5000)
|
||||||
|
|
||||||
await videoUploadPage.navigateTo()
|
await videoUploadPage.navigateTo()
|
||||||
|
|
||||||
|
@ -161,7 +157,7 @@ describe('Videos workflow', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have the playlist in my account', async () => {
|
it('Should have the playlist in my account', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await myAccountPage.navigateToMyPlaylists()
|
await myAccountPage.navigateToMyPlaylists()
|
||||||
|
|
||||||
|
@ -175,26 +171,18 @@ describe('Videos workflow', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should watch the playlist', async () => {
|
it('Should watch the playlist', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await myAccountPage.playPlaylist()
|
await myAccountPage.playPlaylist()
|
||||||
|
|
||||||
const oldValue = await browser.waitForAngularEnabled()
|
await videoWatchPage.waitUntilVideoName(video2Name, 30 * 1000)
|
||||||
await browser.waitForAngularEnabled(false)
|
|
||||||
|
|
||||||
await videoWatchPage.waitUntilVideoName(video2Name, 20000 * 1000)
|
|
||||||
|
|
||||||
await browser.waitForAngularEnabled(oldValue)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should watch the webtorrent playlist in the embed', async () => {
|
it('Should watch the webtorrent playlist in the embed', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
const accessToken = await browser.executeScript(`return window.localStorage.getItem('access_token');`)
|
const accessToken = await browser.execute(`return window.localStorage.getItem('access_token');`)
|
||||||
const refreshToken = await browser.executeScript(`return window.localStorage.getItem('refresh_token');`)
|
const refreshToken = await browser.execute(`return window.localStorage.getItem('refresh_token');`)
|
||||||
|
|
||||||
const oldValue = await browser.waitForAngularEnabled()
|
|
||||||
await browser.waitForAngularEnabled(false)
|
|
||||||
|
|
||||||
await myAccountPage.goOnAssociatedPlaylistEmbed()
|
await myAccountPage.goOnAssociatedPlaylistEmbed()
|
||||||
|
|
||||||
|
@ -202,49 +190,45 @@ describe('Videos workflow', () => {
|
||||||
|
|
||||||
console.log('Will set %s and %s tokens in local storage.', accessToken, refreshToken)
|
console.log('Will set %s and %s tokens in local storage.', accessToken, refreshToken)
|
||||||
|
|
||||||
await browser.executeScript(`window.localStorage.setItem('access_token', '${accessToken}');`)
|
await browser.execute(`window.localStorage.setItem('access_token', '${accessToken}');`)
|
||||||
await browser.executeScript(`window.localStorage.setItem('refresh_token', '${refreshToken}');`)
|
await browser.execute(`window.localStorage.setItem('refresh_token', '${refreshToken}');`)
|
||||||
await browser.executeScript(`window.localStorage.setItem('token_type', 'Bearer');`)
|
await browser.execute(`window.localStorage.setItem('token_type', 'Bearer');`)
|
||||||
|
|
||||||
await browser.refresh()
|
await browser.refresh()
|
||||||
|
|
||||||
await playerPage.playVideo()
|
await playerPage.playVideo()
|
||||||
|
|
||||||
await playerPage.waitUntilPlaylistInfo('2/2')
|
await playerPage.waitUntilPlaylistInfo('2/2', 30 * 1000)
|
||||||
|
|
||||||
await browser.waitForAngularEnabled(oldValue)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should watch the HLS playlist in the embed', async () => {
|
it('Should watch the HLS playlist in the embed', async () => {
|
||||||
const oldValue = await browser.waitForAngularEnabled()
|
|
||||||
await browser.waitForAngularEnabled(false)
|
|
||||||
|
|
||||||
await videoWatchPage.goOnP2PMediaLoaderPlaylistEmbed()
|
await videoWatchPage.goOnP2PMediaLoaderPlaylistEmbed()
|
||||||
|
|
||||||
await playerPage.playVideo()
|
await playerPage.playVideo()
|
||||||
|
|
||||||
await playerPage.waitUntilPlaylistInfo('2/2')
|
await playerPage.waitUntilPlaylistInfo('2/2', 30 * 1000)
|
||||||
|
|
||||||
await browser.waitForAngularEnabled(oldValue)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should delete the video 2', async () => {
|
it('Should delete the video 2', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
// Go to the dev website
|
// Go to the dev website
|
||||||
await browser.get(videoWatchUrl)
|
await go(videoWatchUrl)
|
||||||
|
|
||||||
await myAccountPage.navigateToMyVideos()
|
await myAccountPage.navigateToMyVideos()
|
||||||
|
|
||||||
await myAccountPage.removeVideo(video2Name)
|
await myAccountPage.removeVideo(video2Name)
|
||||||
await myAccountPage.validRemove()
|
await myAccountPage.validRemove()
|
||||||
|
|
||||||
const count = await myAccountPage.countVideos([ videoName, video2Name ])
|
await browser.waitUntil(async () => {
|
||||||
expect(count).toEqual(1)
|
const count = await myAccountPage.countVideos([ videoName, video2Name ])
|
||||||
|
|
||||||
|
return count === 1
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should delete the first video', async () => {
|
it('Should delete the first video', async () => {
|
||||||
if (await skipIfUploadNotSupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await myAccountPage.removeVideo(videoName)
|
await myAccountPage.removeVideo(videoName)
|
||||||
await myAccountPage.validRemove()
|
await myAccountPage.validRemove()
|
||||||
|
|
|
@ -5,9 +5,14 @@
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"types": [
|
"types": [
|
||||||
"jasmine",
|
"node",
|
||||||
"jasminewd2",
|
"webdriverio/async",
|
||||||
"node"
|
"@wdio/mocha-framework",
|
||||||
|
"expect-webdriverio"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"./*.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
import { config as mainConfig } from './wdio.main.conf'
|
||||||
|
|
||||||
|
const user = process.env.BROWSERSTACK_USER
|
||||||
|
const key = process.env.BROWSERSTACK_KEY
|
||||||
|
|
||||||
|
if (!user) throw new Error('Miss browser stack user')
|
||||||
|
if (!key) throw new Error('Miss browser stack key')
|
||||||
|
|
||||||
|
function buildMainOptions (sessionName: string) {
|
||||||
|
return {
|
||||||
|
projectName: 'PeerTube',
|
||||||
|
buildName: 'Main E2E - ' + new Date().toISOString().split('T')[0],
|
||||||
|
sessionName,
|
||||||
|
consoleLogs: 'info',
|
||||||
|
networkLogs: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildBStackDesktopOptions (sessionName: string, resolution?: string) {
|
||||||
|
return {
|
||||||
|
'bstack:options': {
|
||||||
|
...buildMainOptions(sessionName),
|
||||||
|
|
||||||
|
resolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildBStackMobileOptions (sessionName: string, deviceName: string, osVersion: string) {
|
||||||
|
return {
|
||||||
|
'bstack:options': {
|
||||||
|
...buildMainOptions(sessionName),
|
||||||
|
|
||||||
|
realMobile: true,
|
||||||
|
osVersion,
|
||||||
|
deviceName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
config: {
|
||||||
|
...mainConfig,
|
||||||
|
|
||||||
|
user,
|
||||||
|
key,
|
||||||
|
|
||||||
|
maxInstances: 5,
|
||||||
|
|
||||||
|
capabilities: [
|
||||||
|
{
|
||||||
|
browserName: 'Chrome',
|
||||||
|
|
||||||
|
...buildBStackDesktopOptions('Latest Chrome Desktop', '1280x1024')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
browserName: 'Firefox',
|
||||||
|
browserVersion: '68', // ESR
|
||||||
|
|
||||||
|
...buildBStackDesktopOptions('Firefox ESR Desktop', '1280x1024')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
browserName: 'Safari',
|
||||||
|
browserVersion: '11.1',
|
||||||
|
|
||||||
|
...buildBStackDesktopOptions('Safari Desktop', '1280x1024')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
browserName: 'Firefox',
|
||||||
|
|
||||||
|
...buildBStackDesktopOptions('Firefox Latest', '1280x1024')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
browserName: 'Edge',
|
||||||
|
|
||||||
|
...buildBStackDesktopOptions('Edge Latest', '1280x1024')
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
browserName: 'Chrome',
|
||||||
|
|
||||||
|
...buildBStackMobileOptions('Latest Chrome Android', 'Samsung Galaxy S6', '5.0')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
browserName: 'Safari',
|
||||||
|
|
||||||
|
...buildBStackMobileOptions('Safari iPhone', 'iPhone 8 Plus', '11')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
browserName: 'Safari',
|
||||||
|
|
||||||
|
...buildBStackMobileOptions('Safari iPad', 'iPad 7th', '13')
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
host: 'hub-cloud.browserstack.com',
|
||||||
|
connectionRetryTimeout: 240000,
|
||||||
|
waitforTimeout: 20000,
|
||||||
|
|
||||||
|
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": ""}}', [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as WebdriverIO.Config
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { config as mainConfig } from './wdio.main.conf'
|
||||||
|
|
||||||
|
const prefs = {
|
||||||
|
'intl.accept_languages': 'en'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
config: {
|
||||||
|
...mainConfig,
|
||||||
|
|
||||||
|
runner: 'local',
|
||||||
|
|
||||||
|
maxInstances: 1,
|
||||||
|
|
||||||
|
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' ]
|
||||||
|
} as WebdriverIO.Config
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
export const config = {
|
||||||
|
//
|
||||||
|
// ====================
|
||||||
|
// Runner Configuration
|
||||||
|
// ====================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ==================
|
||||||
|
// Specify Test Files
|
||||||
|
// ==================
|
||||||
|
// Define which test specs should run. The pattern is relative to the directory
|
||||||
|
// from which `wdio` was called.
|
||||||
|
//
|
||||||
|
// The specs are defined as an array of spec files (optionally using wildcards
|
||||||
|
// that will be expanded). The test for each spec file will be run in a separate
|
||||||
|
// worker process. In order to have a group of spec files run in the same worker
|
||||||
|
// process simply enclose them in an array within the specs array.
|
||||||
|
//
|
||||||
|
// If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script),
|
||||||
|
// then the current working directory is where your `package.json` resides, so `wdio`
|
||||||
|
// will be called from there.
|
||||||
|
//
|
||||||
|
specs: [
|
||||||
|
'./src/**/*.e2e-spec.ts'
|
||||||
|
],
|
||||||
|
// Patterns to exclude.
|
||||||
|
exclude: [
|
||||||
|
// 'path/to/excluded/files'
|
||||||
|
],
|
||||||
|
//
|
||||||
|
// ===================
|
||||||
|
// Test Configurations
|
||||||
|
// ===================
|
||||||
|
// Define all options that are relevant for the WebdriverIO instance here
|
||||||
|
//
|
||||||
|
// Level of logging verbosity: trace | debug | info | warn | error | silent
|
||||||
|
logLevel: 'info',
|
||||||
|
//
|
||||||
|
// Set specific log levels per logger
|
||||||
|
// loggers:
|
||||||
|
// - webdriver, webdriverio
|
||||||
|
// - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
|
||||||
|
// - @wdio/mocha-framework, @wdio/jasmine-framework
|
||||||
|
// - @wdio/local-runner
|
||||||
|
// - @wdio/sumologic-reporter
|
||||||
|
// - @wdio/cli, @wdio/config, @wdio/utils
|
||||||
|
// Level of logging verbosity: trace | debug | info | warn | error | silent
|
||||||
|
// logLevels: {
|
||||||
|
// webdriver: 'info',
|
||||||
|
// '@wdio/appium-service': 'info'
|
||||||
|
// },
|
||||||
|
//
|
||||||
|
// If you only want to run your tests until a specific amount of tests have failed use
|
||||||
|
// bail (default is 0 - don't bail, run all tests).
|
||||||
|
bail: 1,
|
||||||
|
//
|
||||||
|
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
|
||||||
|
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
|
||||||
|
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
|
||||||
|
// gets prepended directly.
|
||||||
|
baseUrl: 'http://localhost:9001',
|
||||||
|
//
|
||||||
|
// Default timeout for all waitFor* commands.
|
||||||
|
waitforTimeout: 5000,
|
||||||
|
//
|
||||||
|
// Default timeout in milliseconds for request
|
||||||
|
// if browser driver or grid doesn't send response
|
||||||
|
connectionRetryTimeout: 120000,
|
||||||
|
//
|
||||||
|
// Default request retries count
|
||||||
|
connectionRetryCount: 3,
|
||||||
|
|
||||||
|
// Framework you want to run your specs with.
|
||||||
|
// The following are supported: Mocha, Jasmine, and Cucumber
|
||||||
|
// see also: https://webdriver.io/docs/frameworks
|
||||||
|
//
|
||||||
|
// Make sure you have the wdio adapter package for the specific framework installed
|
||||||
|
// before running any tests.
|
||||||
|
framework: 'mocha',
|
||||||
|
//
|
||||||
|
// The number of times to retry the entire specfile when it fails as a whole
|
||||||
|
// specFileRetries: 1,
|
||||||
|
//
|
||||||
|
// Delay in seconds between the spec file retry attempts
|
||||||
|
// specFileRetriesDelay: 0,
|
||||||
|
//
|
||||||
|
// Whether or not retried specfiles should be retried immediately or deferred to the end of the queue
|
||||||
|
// specFileRetriesDeferred: false,
|
||||||
|
//
|
||||||
|
// Test reporter for stdout.
|
||||||
|
// The only one supported by default is 'dot'
|
||||||
|
// see also: https://webdriver.io/docs/dot-reporter
|
||||||
|
reporters: [ 'spec' ],
|
||||||
|
|
||||||
|
//
|
||||||
|
// Options to be passed to Mocha.
|
||||||
|
// See the full list at http://mochajs.org/
|
||||||
|
mochaOpts: {
|
||||||
|
ui: 'bdd',
|
||||||
|
timeout: 60000
|
||||||
|
},
|
||||||
|
|
||||||
|
autoCompileOpts: {
|
||||||
|
autoCompile: true,
|
||||||
|
|
||||||
|
tsNodeOpts: {
|
||||||
|
project: require('path').join(__dirname, './tsconfig.json')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
before: function () {
|
||||||
|
require('expect-webdriverio')
|
||||||
|
require('./src/commands/upload')
|
||||||
|
}
|
||||||
|
} as Partial<WebdriverIO.Config>
|
|
@ -58,8 +58,6 @@
|
||||||
"@types/chart.js": "^2.9.16",
|
"@types/chart.js": "^2.9.16",
|
||||||
"@types/core-js": "^2.5.2",
|
"@types/core-js": "^2.5.2",
|
||||||
"@types/debug": "^4.1.5",
|
"@types/debug": "^4.1.5",
|
||||||
"@types/jasmine": "^3.3.15",
|
|
||||||
"@types/jasminewd2": "^2.0.3",
|
|
||||||
"@types/jschannel": "^1.0.0",
|
"@types/jschannel": "^1.0.0",
|
||||||
"@types/linkifyjs": "^2.1.2",
|
"@types/linkifyjs": "^2.1.2",
|
||||||
"@types/lodash-es": "^4.17.0",
|
"@types/lodash-es": "^4.17.0",
|
||||||
|
@ -71,12 +69,19 @@
|
||||||
"@types/webtorrent": "^0.109.0",
|
"@types/webtorrent": "^0.109.0",
|
||||||
"@typescript-eslint/eslint-plugin": "4.29.3",
|
"@typescript-eslint/eslint-plugin": "4.29.3",
|
||||||
"@typescript-eslint/parser": "4.29.3",
|
"@typescript-eslint/parser": "4.29.3",
|
||||||
|
"@wdio/browserstack-service": "^7.11.1",
|
||||||
|
"@wdio/cli": "^7.11.1",
|
||||||
|
"@wdio/codemod": "^0.9.0",
|
||||||
|
"@wdio/local-runner": "^7.11.1",
|
||||||
|
"@wdio/mocha-framework": "^7.11.1",
|
||||||
|
"@wdio/spec-reporter": "^7.10.1",
|
||||||
"angular2-hotkeys": "^2.1.2",
|
"angular2-hotkeys": "^2.1.2",
|
||||||
"angularx-qrcode": "11.0.0",
|
"angularx-qrcode": "11.0.0",
|
||||||
"bootstrap": "^4.1.3",
|
"bootstrap": "^4.1.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"cache-chunk-store": "^3.0.0",
|
"cache-chunk-store": "^3.0.0",
|
||||||
"chart.js": "^3.5.1",
|
"chart.js": "^3.5.1",
|
||||||
|
"chromedriver": "^92.0.1",
|
||||||
"core-js": "^3.1.4",
|
"core-js": "^3.1.4",
|
||||||
"css-loader": "^6.2.0",
|
"css-loader": "^6.2.0",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
|
@ -85,19 +90,15 @@
|
||||||
"eslint-plugin-import": "^2.24.2",
|
"eslint-plugin-import": "^2.24.2",
|
||||||
"eslint-plugin-jsdoc": "^36.0.8",
|
"eslint-plugin-jsdoc": "^36.0.8",
|
||||||
"eslint-plugin-prefer-arrow": "latest",
|
"eslint-plugin-prefer-arrow": "latest",
|
||||||
|
"expect": "^27.1.0",
|
||||||
|
"expect-webdriverio": "^3.1.2",
|
||||||
"focus-visible": "^5.0.2",
|
"focus-visible": "^5.0.2",
|
||||||
|
"geckodriver": "^2.0.3",
|
||||||
"hls.js": "^1.0.7",
|
"hls.js": "^1.0.7",
|
||||||
"html-loader": "^2.1.2",
|
"html-loader": "^2.1.2",
|
||||||
"html-webpack-plugin": "^5.3.1",
|
"html-webpack-plugin": "^5.3.1",
|
||||||
"https-browserify": "^1.0.0",
|
"https-browserify": "^1.0.0",
|
||||||
"jasmine-core": "~3.8.0",
|
|
||||||
"jasmine-spec-reporter": "~7.0.0",
|
|
||||||
"jschannel": "^1.0.2",
|
"jschannel": "^1.0.2",
|
||||||
"karma": "~6.3.2",
|
|
||||||
"karma-chrome-launcher": "~3.1.0",
|
|
||||||
"karma-coverage-istanbul-reporter": "~3.0.2",
|
|
||||||
"karma-jasmine": "~4.0.1",
|
|
||||||
"karma-jasmine-html-reporter": "^1.5.0",
|
|
||||||
"linkifyjs": "^2.1.5",
|
"linkifyjs": "^2.1.5",
|
||||||
"lodash-es": "^4.17.4",
|
"lodash-es": "^4.17.4",
|
||||||
"markdown-it": "12.2.0",
|
"markdown-it": "12.2.0",
|
||||||
|
@ -106,7 +107,6 @@
|
||||||
"path-browserify": "^1.0.0",
|
"path-browserify": "^1.0.0",
|
||||||
"primeng": "^12.0.0-rc.1",
|
"primeng": "^12.0.0-rc.1",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"protractor": "~7.0.0",
|
|
||||||
"purify-css": "^1.2.5",
|
"purify-css": "^1.2.5",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"rxjs": "^7.3.0",
|
"rxjs": "^7.3.0",
|
||||||
|
@ -129,6 +129,8 @@
|
||||||
"videojs-dock": "^2.0.2",
|
"videojs-dock": "^2.0.2",
|
||||||
"videojs-hotkeys": "^0.2.27",
|
"videojs-hotkeys": "^0.2.27",
|
||||||
"videostream": "~3.2.1",
|
"videostream": "~3.2.1",
|
||||||
|
"wdio-chromedriver-service": "^7.2.0",
|
||||||
|
"wdio-geckodriver-service": "^2.0.3",
|
||||||
"webpack-bundle-analyzer": "^4.4.2",
|
"webpack-bundle-analyzer": "^4.4.2",
|
||||||
"webpack-cli": "^4.7.0",
|
"webpack-cli": "^4.7.0",
|
||||||
"webtorrent": "^1.3.8",
|
"webtorrent": "^1.3.8",
|
||||||
|
|
2463
client/yarn.lock
2463
client/yarn.lock
File diff suppressed because it is too large
Load Diff
|
@ -4,12 +4,6 @@ set -eu
|
||||||
|
|
||||||
npm run clean:server:test
|
npm run clean:server:test
|
||||||
|
|
||||||
(
|
|
||||||
cd client
|
|
||||||
npm run webdriver-manager -- update
|
|
||||||
npm run webpack -- --config webpack/webpack.video-embed.js --mode development
|
|
||||||
)
|
|
||||||
|
|
||||||
npm run concurrently -- -k -s first \
|
npm run concurrently -- -k -s first \
|
||||||
"cd client && npm run ng -- e2e --port 3333 -c local" \
|
"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_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warn\" }, \"signup\": { \"enabled\": false } }' node dist/server"
|
||||||
|
|
|
@ -197,9 +197,6 @@ async function addVideo (options: {
|
||||||
}, sequelizeOptions)
|
}, sequelizeOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel has a new content, set as updated
|
|
||||||
await videoCreated.VideoChannel.setAsUpdated(t)
|
|
||||||
|
|
||||||
await autoBlacklistVideoIfNeeded({
|
await autoBlacklistVideoIfNeeded({
|
||||||
video,
|
video,
|
||||||
user,
|
user,
|
||||||
|
@ -214,6 +211,9 @@ async function addVideo (options: {
|
||||||
return { videoCreated }
|
return { videoCreated }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Channel has a new content, set as updated
|
||||||
|
await videoCreated.VideoChannel.setAsUpdated()
|
||||||
|
|
||||||
createTorrentFederate(video, videoFile)
|
createTorrentFederate(video, videoFile)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) {
|
if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) {
|
||||||
|
|
|
@ -753,7 +753,7 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"`
|
||||||
return this.Actor.isOutdated()
|
return this.Actor.isOutdated()
|
||||||
}
|
}
|
||||||
|
|
||||||
setAsUpdated (transaction: Transaction) {
|
setAsUpdated (transaction?: Transaction) {
|
||||||
return setAsUpdated('videoChannel', this.id, transaction)
|
return setAsUpdated('videoChannel', this.id, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue