Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: nextcloud-libraries/nextcloud-cypress
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0-beta.1
Choose a base ref
...
head repository: nextcloud-libraries/nextcloud-cypress
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.0-beta.2
Choose a head ref
Loading
38 changes: 22 additions & 16 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
day: saturday
time: "03:00"
timezone: Europe/Paris
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: /
schedule:
interval: daily
timezone: Europe/Paris
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies

- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
day: saturday
time: "03:00"
timezone: Europe/Paris
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
timezone: Europe/Paris
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
4 changes: 2 additions & 2 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ jobs:
run: docker pull ghcr.io/nextcloud/continuous-integration-shallow-server

- name: Run E2E cypress tests
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v5
with:
# cypress io
record: true
@@ -94,7 +94,7 @@ jobs:
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"

- name: Run Components cypress tests
uses: cypress-io/github-action@v4
uses: cypress-io/github-action@v5
with:
# to run component tests we need to use "component: true"
component: true
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-approve-merge.yml
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ jobs:

steps:
# Github actions bot approve
- uses: hmarr/auto-approve-action@v2
- uses: hmarr/auto-approve-action@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

2 changes: 1 addition & 1 deletion .github/workflows/node-test.yml
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ jobs:
matrix:
node-version: [ 16, 18 ]
include:
- node-version: 14
- node-version: 16
coverage: coverage

name: test
5 changes: 2 additions & 3 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -34,9 +34,8 @@ export default defineConfig({
videoCompression: false,

e2e: {
// Enable session management and disable isolation
experimentalSessionAndOrigin: true,
testIsolation: 'off',
// Disable session isolation
testIsolation: false,

setupNodeEvents(on, config) {
// Remove container after run
1 change: 0 additions & 1 deletion cypress/dockerNode.ts
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@

import Docker from 'dockerode'
import waitOn from 'wait-on'
import path from 'path'

export const docker = new Docker()

45 changes: 45 additions & 0 deletions cypress/e2e/users.cy.ts
Original file line number Diff line number Diff line change
@@ -52,3 +52,48 @@ describe('Create user and login', function() {
})
})
})

describe('List users and delete user', () => {
const hash = 'user' + randHash()
it(`Create '${hash}' user and delete them`, () => {
const user = new User(hash, 'password')
cy.createUser(user).then(() => {
cy.login(user)
cy.listUsers().then(users => {
expect(users).to.contain(user.userId)
})
})

cy.deleteUser(user).then(() => {
cy.listUsers().then(users => {
expect(users).to.not.contain(user.userId)
})
})
})

it('Fail deleting non existing user', () => {
const hash = 'nouser' + randHash()
const user = new User(hash, 'password')

cy.deleteUser(user).then((response) => {
cy.wrap(response).its('status').should('eq', 404)
})
})
})

describe('Write and read user metadata', () => {
const hash = 'user' + randHash()
it(`Create '${hash}' user and write user data`, () => {
const user = new User(hash, 'password')
cy.createUser(user).then(() => {
cy.login(user)
})

cy.modifyUser(user, 'displayname', 'John Doe')
cy.getUserData(user).then(response => {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response.body, "text/xml");
expect(xmlDoc.querySelector('data displayname')?.textContent).to.eq('John Doe')
})
})
})
118 changes: 117 additions & 1 deletion lib/commands/users.ts
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
*
*/

export class User {
export class User {
userId: string
password: string
language: string
@@ -47,6 +47,8 @@ export const createRandomUser = function(): Cypress.Chainable<User> {

/**
* Create a user
*
* **Warning**: Using this function will reset the previous session
*/
export const createUser = function(user: User): Cypress.Chainable<Cypress.Response<any>> {
const url = `${Cypress.config('baseUrl')}/ocs/v2.php/cloud/users?format=json`.replace('index.php/', '')
@@ -75,6 +77,120 @@ export const createUser = function(user: User): Cypress.Chainable<Cypress.Respon
// Avoid that any follow up request reuses the admin cookies
cy.clearCookies()

return cy.wrap(response)
})
}

/**
* Query list of users on the Nextcloud instance
*
* **Warning**: Using this function will reset the previous session
* @returns list of user IDs
*/
export const listUsers = function(): Cypress.Chainable<string[]> {
const url = `${Cypress.config('baseUrl')}/ocs/v2.php/cloud/users`.replace('index.php/', '')

cy.clearCookies()
return cy.request({
method: 'GET',
url,
auth: {
user: 'admin',
pass: 'admin'
},
headers: {
'OCS-ApiRequest': 'true',
},
}).then((response) => {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response.body, "text/xml");
const users = Array.from(xmlDoc.querySelectorAll('users element')).map(v => v.textContent)

return cy.wrap(users.filter(v => typeof v === 'string') as string[])
})
}

/**
* Delete an user on the Nextcloud instance
*
* **Warning**: Using this function will reset the previous session
* @param user User to delete
*/
export const deleteUser = function(user: User): Cypress.Chainable<Cypress.Response<any>> {
const url = `${Cypress.config('baseUrl')}/ocs/v2.php/cloud/users/${user.userId}`.replace('index.php/', '')

cy.clearCookies()
return cy.request({
method: 'DELETE',
url,
form: true,
auth: {
user: 'admin',
pass: 'admin'
},
headers: {
'OCS-ApiRequest': 'true',
'Content-Type': 'application/x-www-form-urlencoded',
},
failOnStatusCode: false,
}).then((response) => {
cy.log(`Deleted user ${user}`, response.status)
cy.clearCookies()
return cy.wrap(response)
})
}

/**
* Modify an attribute of a given user on the Nextcloud instance
*
* @param user User who performs the modification
* @param key Attribute name
* @param value New attribute value
*/
export const modifyUser = function(user: User, key: string, value: any): Cypress.Chainable<Cypress.Response<any>> {
const url = `${Cypress.config('baseUrl')}/ocs/v2.php/cloud/users/${user.userId}`.replace('index.php/', '')

return cy.request({
method: 'PUT',
url,
form: true,
body: {
key,
value
},
auth: {
user: user.userId,
password: user.password
},
headers: {
'OCS-ApiRequest': 'true',
'Content-Type': 'application/x-www-form-urlencoded',
},
}).then((response) => {
cy.log(`Updated user ${user} ${key} to ${value}`, response.status)
return cy.wrap(response)
})
}

/**
* Query metadata for and in behalf of a given user
*/
export const getUserData = function(user: User): Cypress.Chainable<Cypress.Response<any>> {
const url = `${Cypress.config('baseUrl')}/ocs/v2.php/cloud/users/${user.userId}`.replace('index.php/', '')

return cy.request({
method: 'GET',
url,
auth: {
user: user.userId,
pass: user.password
},
headers: {
'OCS-ApiRequest': 'true',
},
}).then((response) => {
cy.log(`Loaded metadata for user ${user}`, response.status)

return cy.wrap(response)
})
}
76 changes: 58 additions & 18 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
*/
import { getNc } from "./commands"
import { login, logout } from "./commands/sessions"
import { User, createRandomUser, createUser } from "./commands/users"
import { User, createRandomUser, createUser, deleteUser, modifyUser, listUsers, getUserData } from "./commands/users"
import type { Selector } from "./selectors"

declare global {
@@ -32,27 +32,63 @@ declare global {
* @example cy.getNc(FileList)
* cy.getNc(FileRow, { id: fileInfo.id })
*/
getNc(selector: Selector, args?: Object): Cypress.Chainable<JQuery<HTMLElement>>
getNc(selector: Selector, args?: Object): Cypress.Chainable<JQuery<HTMLElement>>

/**
* Login on a Nextcloud instance
*/
login(user: User): void
/**
* Login on a Nextcloud instance
*/
login(user: User): void

/**
* Logout from a Nextcloud instance
*/
logout(): void

/**
* Create a random user on the Nextcloud instance
*
* **Warning**: Using this function will reset the previous session
*/
createRandomUser(): Cypress.Chainable<User>

/**
* Create a user on the Nextcloud instance
*
* **Warning**: Using this function will reset the previous session
*/
createUser(user: User): Cypress.Chainable<Cypress.Response<any>>

/**
* Logout from a Nextcloud instance
*/
logout(): void
/**
* Delete a user on the Nextcloud instance
*
* **Warning**: Using this function will reset the previous session
*/
deleteUser(user: User): Cypress.Chainable<Cypress.Response<any>>

/**
* Query list of users on the Nextcloud instance
*
* **Warning**: Using this function will reset the previous session
* @returns list of user IDs
*/
listUsers(): Cypress.Chainable<string[]>

/**
* Create a random user on the Nextcloud instance
*/
createRandomUser(): Cypress.Chainable<User>
/**
* Modify an attribute of a given user on the Nextcloud instance
*
* @param user User who modifies their metadata
* @param key Attribute name
* @param value New attribute value
*/
modifyUser(user: User, key: string, value: any): Cypress.Chainable<Cypress.Response<any>>

/**
* Create a user on the Nextcloud instance
*/
createUser(user: User): Cypress.Chainable<Cypress.Response<any>>
/**
*
* Query metadata for, and in behalf, of a given user
*
* @param user User whom metadata to query
*/
getUserData(user: User): Cypress.Chainable<Cypress.Response<any>>
}
}
}
@@ -70,6 +106,10 @@ export const addCommands = function() {
Cypress.Commands.add('logout', logout)
Cypress.Commands.add('createRandomUser', createRandomUser)
Cypress.Commands.add('createUser', createUser)
Cypress.Commands.add('deleteUser', deleteUser)
Cypress.Commands.add('listUsers', listUsers)
Cypress.Commands.add('modifyUser', modifyUser)
Cypress.Commands.add('getUserData', getUserData)
}

export { User }
Loading