- pull_request
- push
----
-kind: pipeline
-name: acceptance-login
-
-steps:
-- name: submodules
- image: ghcr.io/nextcloud/continuous-integration-alpine-git:latest
- commands:
- - git submodule update --init
-- name: acceptance-login
- image: ghcr.io/nextcloud/continuous-integration-acceptance-php8.0:latest
- commands:
- - tests/acceptance/run-local.sh --timeout-multiplier 10 --nextcloud-server-domain acceptance-login --selenium-server selenium:4444 allow-git-repository-modifications features/login.feature
-
-services:
-- name: selenium
- image: ghcr.io/nextcloud/continuous-integration-selenium:3.141.59
- environment:
- # Reduce default log level for Selenium server (INFO) as it is too
- # verbose.
- JAVA_OPTS: -Dselenium.LOGGER.level=WARNING
-
-trigger:
- branch:
- - master
- - stable*
- event:
- - pull_request
- - push
-
---
kind: pipeline
name: acceptance-users
--- /dev/null
+import type { User } from '@nextcloud/cypress'
+
+describe('Login', () => {
+ let user: User
+ let disabledUser: User
+
+ after(() => cy.deleteUser(user))
+ before(() => {
+ // disable brute force protection
+ cy.runOccCommand('config:system:set auth.bruteforce.protection.enabled --value false --type bool')
+ cy.createRandomUser().then(($user) => {
+ user = $user
+ })
+ cy.createRandomUser().then(($user) => {
+ disabledUser = $user
+ cy.runOccCommand(`user:disable '${disabledUser.userId}'`)
+ })
+ })
+
+ beforeEach(() => {
+ cy.logout()
+ })
+
+ it('log in with valid user and password', () => {
+ // Given I visit the Home page
+ cy.visit('/')
+ // I see the login page
+ cy.get('form[name="login"]').should('be.visible')
+ // I log in with a valid user
+ cy.get('form[name="login"]').within(() => {
+ cy.get('input[name="user"]').type(user.userId)
+ cy.get('input[name="password"]').type(user.password)
+ cy.contains('button[data-login-form-submit]', 'Log in').click()
+ })
+
+ // see that the login is done
+ cy.get('[data-login-form-submit]').if().should('not.contain', 'Logging in')
+
+ // Then I see that the current page is the Files app
+ cy.url().should('match', /apps\/dashboard(\/|$)/)
+ })
+
+ it('try to log in with valid user and invalid password', () => {
+ // Given I visit the Home page
+ cy.visit('/')
+ // I see the login page
+ cy.get('form[name="login"]').should('be.visible')
+ // I log in with a valid user but invalid password
+ cy.get('form[name="login"]').within(() => {
+ cy.get('input[name="user"]').type(user.userId)
+ cy.get('input[name="password"]').type(`${user.password}--wrong`)
+ cy.contains('button', 'Log in').click()
+ })
+
+ // see that the login is done
+ cy.get('[data-login-form-submit]').if().should('not.contain', 'Logging in')
+
+ // Then I see that the current page is the Login page
+ cy.url().should('match', /\/login/)
+ // And I see that a wrong password message is shown
+ cy.get('form[name="login"]').then(($el) => expect($el.text()).to.match(/Wrong.+password/i))
+ cy.get('input[name="password"]:invalid').should('exist')
+ })
+
+ it('try to log in with valid user and invalid password', () => {
+ // Given I visit the Home page
+ cy.visit('/')
+ // I see the login page
+ cy.get('form[name="login"]').should('be.visible')
+ // I log in with a valid user but invalid password
+ cy.get('form[name="login"]').within(() => {
+ cy.get('input[name="user"]').type(user.userId)
+ cy.get('input[name="password"]').type(`${user.password}--wrong`)
+ cy.contains('button', 'Log in').click()
+ })
+
+ // see that the login is done
+ cy.get('[data-login-form-submit]').if().should('not.contain', 'Logging in')
+
+ // Then I see that the current page is the Login page
+ cy.url().should('match', /\/login/)
+ // And I see that a wrong password message is shown
+ cy.get('form[name="login"]').then(($el) => expect($el.text()).to.match(/Wrong.+password/i).and.to.match(/Wrong.+username/))
+ cy.get('input[name="password"]:invalid').should('exist')
+ })
+
+ it('try to log in with invalid user', () => {
+ // Given I visit the Home page
+ cy.visit('/')
+ // I see the login page
+ cy.get('form[name="login"]').should('be.visible')
+ // I log in with an invalid user but valid password
+ cy.get('form[name="login"]').within(() => {
+ cy.get('input[name="user"]').type(`${user.userId}--wrong`)
+ cy.get('input[name="password"]').type(user.password)
+ cy.contains('button', 'Log in').click()
+ })
+
+ // see that the login is done
+ cy.get('[data-login-form-submit]').if().should('not.contain', 'Logging in')
+
+ // Then I see that the current page is the Login page
+ cy.url().should('match', /\/login/)
+ // And I see that a wrong password message is shown
+ cy.get('form[name="login"]').then(($el) => expect($el.text()).to.match(/Wrong.+password/i).and.to.match(/Wrong.+username/))
+ cy.get('input[name="password"]:invalid').should('exist')
+ })
+
+ it('try to log in as disabled user', () => {
+ // Given I visit the Home page
+ cy.visit('/')
+ // I see the login page
+ cy.get('form[name="login"]').should('be.visible')
+ // When I log in with user disabledUser and password
+ cy.get('form[name="login"]').within(() => {
+ cy.get('input[name="user"]').type(disabledUser.userId)
+ cy.get('input[name="password"]').type(disabledUser.password)
+ cy.contains('button', 'Log in').click()
+ })
+
+ // see that the login is done
+ cy.get('[data-login-form-submit]').if().should('not.contain', 'Logging in')
+
+ // Then I see that the current page is the Login page
+ cy.url().should('match', /\/login/)
+ // And I see that the disabled user message is shown
+ cy.get('form[name="login"]').then(($el) => expect($el.text()).to.match(/User.+disabled/i))
+ cy.get('input[name="password"]:invalid').should('exist')
+ })
+
+ it('try to logout', () => {
+ cy.login(user)
+
+ // Given I visit the Home page
+ cy.visit('/')
+ // I see the dashboard
+ cy.url().should('match', /apps\/dashboard(\/|$)/)
+
+ // When click logout
+ cy.get('#user-menu button').should('exist').click()
+ cy.get('#logout a').should('contain.text', 'Log out').click()
+
+ // Then I see that the current page is the Login page
+ cy.url().should('match', /\/login/)
+ })
+})
- FileListContext
- FilesAppContext
- FilesAppSharingContext
- - LoginPageContext
- NotificationsContext
- PublicShareContext
- SearchContext
- FileListContext
- FilesAppContext
- FilesAppSharingContext
- - LoginPageContext
- NotificationsContext
- PublicShareContext
- SearchContext
+++ /dev/null
-<?php
-
-/**
- *
- * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-use Behat\Behat\Context\Context;
-use Behat\Behat\Hook\Scope\BeforeScenarioScope;
-use PHPUnit\Framework\Assert;
-
-class LoginPageContext implements Context, ActorAwareInterface {
- use ActorAware;
-
- /**
- * @var FeatureContext
- */
- private $featureContext;
-
- /**
- * @var FilesAppContext
- */
- private $filesAppContext;
-
- public static function userNameField(): Locator {
- return Locator::forThe()->field("user")->
- describedAs("User name field in Login page");
- }
-
- public static function passwordField(): Locator {
- return Locator::forThe()->field("password")->
- describedAs("Password field in Login page");
- }
-
- public static function loginButton(): Locator {
- return Locator::forThe()->css(".button-vue[type='submit']")->
- describedAs("Login button in Login page");
- }
-
- public static function wrongPasswordMessage(): Locator {
- return Locator::forThe()->xpath("//*[@class = 'input-field__helper-text-message input-field__helper-text-message--error' and normalize-space() = 'Wrong username or password.']")->
- describedAs("Wrong password message in Login page");
- }
-
- /**
- * @return Locator
- */
- public static function userDisabledMessage() {
- return Locator::forThe()->xpath("//*[@class = 'input-field__helper-text-message input-field__helper-text-message--error' and normalize-space() = 'User disabled']")->
- describedAs('User disabled message on login page');
- }
-
- /**
- * @When I log in with user :user and password :password
- */
- public function iLogInWithUserAndPassword(string $user, string $password): void {
- $this->actor->find(self::userNameField(), 10)->setValue($user);
- $this->actor->find(self::passwordField())->setValue($password);
- $this->actor->find(self::loginButton())->click();
- }
-
- /**
- * @Then I see that the current page is the Login page
- */
- public function iSeeThatTheCurrentPageIsTheLoginPage() {
- Assert::assertStringStartsWith(
- $this->actor->locatePath("/login"),
- $this->actor->getSession()->getCurrentUrl());
- }
-
- /**
- * @Then I see that a wrong password message is shown
- */
- public function iSeeThatAWrongPasswordMessageIsShown() {
- Assert::assertTrue(
- $this->actor->find(self::wrongPasswordMessage(), 10)->isVisible());
- }
-
- /**
- * @Then I see that the disabled user message is shown
- */
- public function iSeeThatTheDisabledUserMessageIsShown() {
- Assert::assertTrue(
- $this->actor->find(self::userDisabledMessage(), 10)->isVisible());
- }
-
- /**
- * @BeforeScenario
- */
- public function getOtherRequiredSiblingContexts(BeforeScenarioScope $scope) {
- $environment = $scope->getEnvironment();
-
- $this->featureContext = $environment->getContext("FeatureContext");
- $this->filesAppContext = $environment->getContext("FilesAppContext");
- }
-
- /**
- * @Given I am logged in
- */
- public function iAmLoggedIn() {
- $this->featureContext->iVisitTheHomePage();
- $this->iLogInWithUserAndPassword("user0", "123456acb");
- $this->filesAppContext->iSeeThatTheCurrentPageIsTheFilesApp();
- }
-
- /**
- * @Given I am logged in as :userName
- */
- public function iAmLoggedInAs($userName) {
- $this->featureContext->iVisitTheHomePage();
- $this->iLogInWithUserAndPassword($userName, "123456acb");
- $this->filesAppContext->iSeeThatTheCurrentPageIsTheFilesApp();
- }
-
- /**
- * @Given I am logged in as the admin
- */
- public function iAmLoggedInAsTheAdmin() {
- $this->featureContext->iVisitTheHomePage();
- $this->iLogInWithUserAndPassword("admin", "admin");
- $this->filesAppContext->iSeeThatTheCurrentPageIsTheFilesApp();
- }
-
- /**
- * @Given I can not log in with user :user and password :password
- */
- public function iCanNotLogInWithUserAndPassword($user, $password) {
- $this->featureContext->iVisitTheHomePage();
- $this->iLogInWithUserAndPassword($user, $password);
- $this->iSeeThatTheCurrentPageIsTheLoginPage();
- $this->iSeeThatAWrongPasswordMessageIsShown();
- }
-}
+++ /dev/null
-@apache
-Feature: login
-
- Scenario: log in with valid user and password
- Given I visit the Home page
- When I log in with user user0 and password 123456acb
- Then I see that the current page is the Files app
-
- Scenario: try to log in with valid user and invalid password
- Given I visit the Home page
- When I log in with user user0 and password 654321
- Then I see that the current page is the Login page
- And I see that a wrong password message is shown
-
-# Scenario: log in with valid user and invalid password once fixed by admin
-# Given I act as John
-# And I can not log in with user user0 and password 654231
-# When I act as Jane
-# And I am logged in as the admin
-# And I open the User settings
-# And I set the password for user0 to 654321
-# And I act as John
-# And I log in with user user0 and password 654321
-# Then I see that the current page is the Files app
-
- Scenario: try to log in with invalid user
- Given I visit the Home page
- When I log in with user unknownUser and password 123456acb
- Then I see that the current page is the Login page
- And I see that a wrong password message is shown
-
- Scenario: try to log in as disabled user
- Given I visit the Home page
- When I log in with user disabledUser and password 123456acb
- Then I see that the current page is the Login page
- And I see that the disabled user message is shown
-
- Scenario: log in with invalid user once fixed by admin
- Given I act as John
- And I can not log in with user unknownUser and password 123456acb
- When I act as Jane
- And I am logged in as the admin
- And I open the User settings
- And I click the New user button
- And I see that the new user form is shown
- And I create user unknownUser with password 123456acb
- # And I see that the list of users contains the user unknownUser
- And I act as John
- And I log in with user unknownUser and password 123456acb
- Then I see that the current page is the Files app
-
- Scenario: log out
- Given I am logged in
- When I log out
- Then I see that the current page is the Login page