kopia lustrzana https://github.com/nextcloud/social
Fix cypress workflow
Signed-off-by: Louis Chemineau <louis@chmn.me>pull/1558/head
rodzic
df8d5fdad4
commit
74308c64ff
|
@ -11,50 +11,78 @@ env:
|
|||
APP_NAME: social
|
||||
BRANCH: ${{ github.base_ref }}
|
||||
CYPRESS_baseUrl: http://127.0.0.1:8082/index.php
|
||||
TESTING: true
|
||||
|
||||
jobs:
|
||||
cypress:
|
||||
init:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# run 2 copies of the current job in parallel
|
||||
containers: [1, 2]
|
||||
node-version: ['12']
|
||||
php-versions: ['7.4']
|
||||
|
||||
name: Runner ${{ matrix.containers }}
|
||||
|
||||
steps:
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup server
|
||||
run: |
|
||||
cd cypress
|
||||
docker-compose up -d
|
||||
- name: Set up node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@v1.1
|
||||
id: versions
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
fallbackNode: "^12"
|
||||
fallbackNpm: "^6"
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
cache: "npm"
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
|
||||
|
||||
- name: Install dependencies & build app
|
||||
run: |
|
||||
npm ci
|
||||
composer install
|
||||
TESTING=true npm run build --if-present
|
||||
- name: Wait for server
|
||||
|
||||
- name: Save context
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: cypress-context-${{ github.run_id }}
|
||||
path: /home/runner/work/social
|
||||
|
||||
cypress:
|
||||
runs-on: ubuntu-latest
|
||||
needs: init
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# run multiple copies of the current job in parallel
|
||||
containers: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
|
||||
name: runner ${{ matrix.containers }}
|
||||
|
||||
steps:
|
||||
- name: Restore context
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: cypress-context-${{ github.run_id }}
|
||||
path: /home/runner/work/social
|
||||
|
||||
- name: Setup server
|
||||
run: |
|
||||
npm install -g wait-on
|
||||
wait-on -i 500 -t 240000 $CYPRESS_baseUrl
|
||||
cd cypress
|
||||
docker-compose up -d
|
||||
|
||||
- name: Wait for server
|
||||
run: npm run wait-on $CYPRESS_baseUrl
|
||||
|
||||
- name: Enable app & configure server
|
||||
run: |
|
||||
cd cypress
|
||||
docker-compose exec --env APP_NAME=${{ env.APP_NAME }} -T nextcloud bash /initserver.sh
|
||||
docker-compose exec --env APP_NAME=${{ env.APP_NAME }} --env BRANCH=${{ env.BRANCH }} -T nextcloud bash /initserver.sh
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v1
|
||||
uses: cypress-io/github-action@v4
|
||||
with:
|
||||
record: true
|
||||
parallel: true
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
const { defineConfig } = require('cypress')
|
||||
const browserify = require('@cypress/browserify-preprocessor')
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: '7mqhfh',
|
||||
|
||||
viewportWidth: 1280,
|
||||
viewportHeight: 720,
|
||||
defaultCommandTimeout: 6000,
|
||||
retries: 1,
|
||||
|
||||
env: {
|
||||
failSilently: false,
|
||||
type: 'actual',
|
||||
},
|
||||
|
||||
screenshotsFolder: 'cypress/snapshots/actual',
|
||||
trashAssetsBeforeRuns: true,
|
||||
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:8082/index.php',
|
||||
|
||||
setupNodeEvents(on, config) {
|
||||
// Fix browserslist extend https://github.com/cypress-io/cypress/issues/2983#issuecomment-570616682
|
||||
on('file:preprocessor', browserify())
|
||||
},
|
||||
},
|
||||
})
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"baseUrl": "http://localhost:8082/index.php/",
|
||||
"projectId": "7mqhfh",
|
||||
"viewportWidth": 1280,
|
||||
"viewportHeight": 720,
|
||||
"defaultCommandTimeout": 6000
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
version: '3'
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
nextcloud:
|
||||
image: nextcloudci/server
|
||||
image: ghcr.io/nextcloud/continuous-integration-shallow-server
|
||||
|
||||
ports:
|
||||
- 8082:80
|
||||
|
||||
environment:
|
||||
CYPRESS_baseUrl: "http://127.0.0.1:8082/index.php"
|
||||
BRANCH: master
|
||||
BRANCH: "${BRANCH:-master}"
|
||||
|
||||
volumes:
|
||||
- ../:/var/www/html/apps/social
|
||||
# Using fallback to make sure this script doesn't mess
|
||||
# with the mounting if APP_NAME is not provided.
|
||||
- ../:/var/www/html/apps/${APP_NAME:-social}
|
||||
- ./initserver.sh:/initserver.sh
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
let userId = 'janedoe' + Date.now();
|
||||
const userId = 'janedoe' + Date.now()
|
||||
|
||||
describe('Social app setup', function() {
|
||||
before(function() {
|
||||
|
@ -6,10 +6,6 @@ describe('Social app setup', function() {
|
|||
cy.login(userId, 'p4ssw0rd')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
Cypress.Cookies.preserveOnce('nc_username', 'nc_token', 'nc_session_id', 'oc_sessionPassphrase');
|
||||
})
|
||||
|
||||
it('See the welcome message', function() {
|
||||
cy.visit('/apps/social/')
|
||||
cy.get('.social__welcome').should('contain', 'Nextcloud becomes part of the federated social networks!')
|
||||
|
@ -26,7 +22,7 @@ describe('Social app setup', function() {
|
|||
cy.get('.app-navigation').contains('Direct messages').click()
|
||||
cy.get('.emptycontent').should('be.visible').contains('No direct messages found')
|
||||
cy.get('.app-navigation').contains('Profile').click()
|
||||
cy.get('.emptycontent').should('be.visible').contains('You haven\'t tooted yet')
|
||||
cy.get('.emptycontent').should('be.visible').contains('You have not tooted yet')
|
||||
})
|
||||
|
||||
})
|
|
@ -20,15 +20,17 @@
|
|||
*
|
||||
*/
|
||||
|
||||
let userId = 'janedoe' + Date.now();
|
||||
const userId = 'janedoe' + Date.now()
|
||||
|
||||
describe('Create posts', function() {
|
||||
|
||||
before(function() {
|
||||
// ensure that the admin account is initialized for social
|
||||
cy.login('admin', 'admin', '/apps/social/')
|
||||
|
||||
|
||||
cy.nextcloudCreateUser(userId, 'p4ssw0rd')
|
||||
cy.logout()
|
||||
|
||||
cy.login(userId, 'p4ssw0rd', '/apps/social/')
|
||||
cy.get('.app-content').should('be.visible')
|
||||
})
|
||||
|
@ -37,10 +39,6 @@ describe('Create posts', function() {
|
|||
cy.screenshot()
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
Cypress.Cookies.preserveOnce('nc_username', 'nc_token', 'nc_session_id', 'oc_sessionPassphrase');
|
||||
})
|
||||
|
||||
it('See the empty content illustration', function() {
|
||||
cy.get('.emptycontent').should('be.visible').contains('No posts found')
|
||||
})
|
||||
|
@ -49,19 +47,19 @@ describe('Create posts', function() {
|
|||
cy.visit('/apps/social/')
|
||||
cy.server()
|
||||
cy.route('POST', '/index.php/apps/social/api/v1/post').as('postMessage')
|
||||
cy.get('.new-post input[type=submit]')
|
||||
cy.get('.new-post button[type=submit]')
|
||||
.should('be.disabled')
|
||||
cy.get('.new-post').find('[contenteditable]').type('Hello world')
|
||||
cy.get('.new-post input[type=submit]')
|
||||
cy.get('.new-post button[type=submit]')
|
||||
.should('not.be.disabled')
|
||||
cy.get('.new-post input[type=submit]')
|
||||
cy.get('.new-post button[type=submit]')
|
||||
.click()
|
||||
cy.wait('@postMessage')
|
||||
cy.get('.social__timeline div.timeline-entry:first-child').should('contain', 'Hello world')
|
||||
})
|
||||
|
||||
it('No longer see the empty content illustration', function() {
|
||||
cy.get('.emptycontent').should('not.be.visible')
|
||||
cy.get('.emptycontent').should('not.exist')
|
||||
})
|
||||
|
||||
it('Write a post to followers with shift enter', function() {
|
||||
|
@ -78,11 +76,11 @@ describe('Create posts', function() {
|
|||
cy.server()
|
||||
cy.route('POST', '/index.php/apps/social/api/v1/post').as('postMessage')
|
||||
cy.route('GET', '/index.php/apps/social/api/v1/global/accounts/search')
|
||||
cy.get('.new-post').find('[contenteditable]').type('@adm', {delay: 500})
|
||||
cy.get('.new-post').find('[contenteditable]').type('@adm', { delay: 500 })
|
||||
cy.get('.tribute-container').should('be.visible')
|
||||
cy.get('.tribute-container ul li:first').contains('admin')
|
||||
cy.get('.new-post').find('[contenteditable]').type('{enter} Hello there', {delay: 100, force: true})
|
||||
cy.get('.new-post input[type=submit]')
|
||||
cy.get('.new-post').find('[contenteditable]').type('{enter} Hello there', { delay: 100, force: true })
|
||||
cy.get('.new-post button[type=submit]')
|
||||
.click()
|
||||
cy.wait('@postMessage')
|
||||
cy.get('.social__timeline div.timeline-entry:first-child').should('contain', '@admin')
|
||||
|
@ -93,9 +91,9 @@ describe('Create posts', function() {
|
|||
cy.server()
|
||||
cy.route('POST', '/index.php/apps/social/api/v1/post').as('postMessage')
|
||||
cy.route('GET', '/index.php/apps/social/api/v1/global/accounts/search')
|
||||
cy.get('.new-post').find('[contenteditable]').click({force: true}).type('@adm{enter} Hello world', {delay: 500, force: true})
|
||||
cy.get('.new-post').find('[contenteditable]').click({ force: true }).type('@adm{enter} Hello world', { delay: 500, force: true })
|
||||
cy.wait(500)
|
||||
cy.get('.new-post input[type=submit]').should('not.be.disabled')
|
||||
cy.get('.new-post button[type=submit]').should('not.be.disabled')
|
||||
const visibilityButton = cy.get('.new-post .options > div > button')
|
||||
visibilityButton.should('have.class', 'icon-contacts-dark')
|
||||
|
||||
|
@ -105,7 +103,7 @@ describe('Create posts', function() {
|
|||
visibilityButton.click()
|
||||
cy.get('.new-post-form .popovermenu').should('not.be.visible')
|
||||
|
||||
cy.get('.new-post input[type=submit]')
|
||||
cy.get('.new-post button[type=submit]')
|
||||
.click()
|
||||
cy.wait('@postMessage')
|
||||
cy.get('.social__timeline div.timeline-entry:first-child').should('contain', 'Hello world').should('contain', '@admin')
|
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
echo "APP_NAME: $APP_NAME"
|
||||
echo "BRANCH: $BRANCH"
|
||||
|
||||
chown -R www-data:www-data /var/www/html/data
|
||||
|
||||
su www-data -c "
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
const {
|
||||
addMatchImageSnapshotPlugin
|
||||
} = require('cypress-image-snapshot/plugin')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
addMatchImageSnapshotPlugin(on, config)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
# RUN THIS SCRIPT FROM THE ROOT FOLDER OF YOUR APP
|
||||
APP_NAME=${PWD##*/}
|
||||
CYPRESS_baseUrl=http://127.0.0.1:8082/index.php
|
||||
|
||||
if [[ $APP_NAME == "cypress" ]]
|
||||
then
|
||||
|
@ -8,13 +9,11 @@ then
|
|||
else
|
||||
echo "Launching docker server for the $APP_NAME app"
|
||||
cd cypress
|
||||
docker-compose up -d
|
||||
echo -n "Waiting for server start "
|
||||
until [[ $(docker-compose exec -u www-data -T nextcloud php ./occ status --output=json) == *"\"installed\":true"* ]]
|
||||
do
|
||||
echo -n "."
|
||||
done
|
||||
echo ""
|
||||
docker-compose pull
|
||||
docker-compose up -d --force-recreate
|
||||
npm run wait-on $CYPRESS_baseUrl
|
||||
echo "Nextcloud successfully installed"
|
||||
docker-compose exec --env APP_NAME=$APP_NAME -T nextcloud bash /initserver.sh
|
||||
docker-compose exec -u www-data -T nextcloud php ./occ social:reset -n
|
||||
docker-compose exec -u www-data -T nextcloud php ./occ social:reset -n
|
||||
echo "Nextcloud successfully configured"
|
||||
fi
|
||||
|
|
|
@ -20,37 +20,45 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
addMatchImageSnapshotCommand()
|
||||
|
||||
const url = Cypress.config('baseUrl').replace(/\/index.php\/?$/g, '')
|
||||
Cypress.env('baseUrl', url)
|
||||
|
||||
Cypress.Commands.add('login', (user, password, route = '/apps/files') => {
|
||||
cy.clearCookies();
|
||||
Cypress.Cookies.defaults({
|
||||
preserve: /^(oc|nc)/,
|
||||
})
|
||||
cy.visit(route)
|
||||
cy.get('input[name=user]').type(user)
|
||||
cy.get('input[name=password]').type(password)
|
||||
cy.get('#submit-wrapper input[type=submit]').click()
|
||||
cy.get('form[name=login] [type=submit]').click()
|
||||
cy.url().should('include', route)
|
||||
})
|
||||
|
||||
Cypress.Commands.add('logout', () => {
|
||||
if (Cypress.$("input[name=user]").length > 0) {
|
||||
// already logged out
|
||||
} else {
|
||||
cy.get('#expanddiv li[data-id="logout"] a').then(logout => {
|
||||
if (logout) {
|
||||
cy.visit(logout[0].href)
|
||||
cy.getCookies()
|
||||
.then(cookies => {
|
||||
if (cookies.length === 0) {
|
||||
cy.log('Not logged, skipping logout...')
|
||||
return
|
||||
}
|
||||
|
||||
return cy.get('body')
|
||||
.then($body => {
|
||||
const $settingsButton = $body.find('#settings #expand')
|
||||
if ($settingsButton.length === 0) {
|
||||
cy.log('Not logged in.')
|
||||
return
|
||||
}
|
||||
|
||||
$settingsButton.click()
|
||||
cy.contains('Log out').click()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Cypress.Commands.add('nextcloudCreateUser', (user, password) => {
|
||||
cy.clearCookies();
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `${Cypress.env('baseUrl')}/ocs/v1.php/cloud/users?format=json`,
|
||||
|
@ -61,13 +69,12 @@ Cypress.Commands.add('nextcloudCreateUser', (user, password) => {
|
|||
},
|
||||
auth: { user: 'admin', pass: 'admin' },
|
||||
headers: {
|
||||
'OCS-ApiRequest': 'true',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
Authorization: `Basic ${btoa('admin:admin')}`,
|
||||
'OCS-ApiRequest': 'true',
|
||||
Authorization: `Basic ${Buffer.from('admin:admin').toString('base64')}`,
|
||||
},
|
||||
}).then(response => {
|
||||
cy.log(`Created user ${user}`, response.status)
|
||||
})
|
||||
cy.clearCookies()
|
||||
})
|
||||
|
||||
Cypress.Commands.add('uploadFile', (fileName, mimeType, path = '') => {
|
||||
|
@ -82,7 +89,7 @@ Cypress.Commands.add('uploadFile', (fileName, mimeType, path = '') => {
|
|||
headers: {
|
||||
requesttoken: window.OC.requestToken,
|
||||
'Content-Type': mimeType,
|
||||
}
|
||||
},
|
||||
}).then(response => {
|
||||
cy.log(`Uploaded ${fileName}`, response)
|
||||
})
|
||||
|
@ -122,7 +129,7 @@ Cypress.Commands.add('deleteFile', fileName => {
|
|||
* Create a share link and return the share url
|
||||
*
|
||||
* @param {string} path the file/folder path
|
||||
* @returns {string} the share link url
|
||||
* @return {string} the share link url
|
||||
*/
|
||||
Cypress.Commands.add('createLinkShare', path => {
|
||||
return cy.window().then(async window => {
|
||||
|
@ -133,26 +140,15 @@ Cypress.Commands.add('createLinkShare', path => {
|
|||
}, {
|
||||
headers: {
|
||||
requesttoken: window.OC.requestToken,
|
||||
}
|
||||
},
|
||||
})
|
||||
if (!('ocs' in request.data) || !('token' in request.data.ocs.data && request.data.ocs.data.token.length > 0)) {
|
||||
throw request
|
||||
}
|
||||
cy.log('Share link created', request.data.ocs.data.token)
|
||||
return cy.wrap(request.data.ocs.data.token)
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}).should('have.length', 15)
|
||||
})
|
||||
|
||||
Cypress.Commands.overwrite('matchImageSnapshot', (originalFn, subject, name, options) => {
|
||||
// hide avatar because random colour break the visual regression tests
|
||||
cy.window().then(window => {
|
||||
const avatarDiv = window.document.querySelector('.avatardiv')
|
||||
if (avatarDiv) {
|
||||
avatarDiv.remove()
|
||||
}
|
||||
})
|
||||
return originalFn(subject, name, options)
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// This example support/e2e.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
|
@ -14,7 +14,4 @@
|
|||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
import './commands.js'
|
Plik diff jest za duży
Load Diff
10
package.json
10
package.json
|
@ -25,8 +25,9 @@
|
|||
"lint:fix": "eslint --ext .js,.vue src --fix",
|
||||
"test": "jest",
|
||||
"test:coverage": "jest --coverage",
|
||||
"cypress": "cypress run",
|
||||
"cypress:gui": "cypress open"
|
||||
"cypress": "./cypress/start.sh; cypress run; ./cypress/stop.sh",
|
||||
"cypress:gui": "./cypress/start.sh; cypress open; ./cypress/stop.sh",
|
||||
"wait-on": "wait-on -i 500 -t 300000"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^2.0.0",
|
||||
|
@ -72,13 +73,16 @@
|
|||
"npm": "^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/browserify-preprocessor": "^3.0.2",
|
||||
"@nextcloud/babel-config": "^1.0.0",
|
||||
"@nextcloud/browserslist-config": "^2.3.0",
|
||||
"@nextcloud/eslint-config": "^8.1.4",
|
||||
"@nextcloud/webpack-vue-config": "^5.4.0",
|
||||
"cypress": "^11.2.0",
|
||||
"jest": "^29.3.1",
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"vue-template-compiler": "^2.7.10"
|
||||
"vue-template-compiler": "^2.7.10",
|
||||
"wait-on": "^7.0.1"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
<div class="emptySpace" />
|
||||
<NcButton :value="currentVisibilityPostLabel"
|
||||
:disabled="!canPost"
|
||||
native-type="submit"
|
||||
type="primary"
|
||||
@click.prevent="createPost">
|
||||
<template #icon>
|
||||
|
|
Ładowanie…
Reference in New Issue