Fix cypress workflow

Signed-off-by: Louis Chemineau <louis@chmn.me>
pull/1558/head
Louis Chemineau 2023-01-04 15:36:33 +01:00
rodzic df8d5fdad4
commit 74308c64ff
14 zmienionych plików z 5208 dodań i 744 usunięć

Wyświetl plik

@ -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

28
cypress.config.js 100644
Wyświetl plik

@ -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())
},
},
})

Wyświetl plik

@ -1,7 +0,0 @@
{
"baseUrl": "http://localhost:8082/index.php/",
"projectId": "7mqhfh",
"viewportWidth": 1280,
"viewportHeight": 720,
"defaultCommandTimeout": 6000
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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')
})
})

Wyświetl plik

@ -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')

Wyświetl plik

@ -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 "

Wyświetl plik

@ -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)
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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)
})

Wyświetl plik

@ -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'

5680
package-lock.json wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -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": [

Wyświetl plik

@ -120,6 +120,7 @@
<div class="emptySpace" />
<NcButton :value="currentVisibilityPostLabel"
:disabled="!canPost"
native-type="submit"
type="primary"
@click.prevent="createPost">
<template #icon>