mirror of
https://github.com/LibreSign/libresign.git
synced 2025-12-18 05:20:45 +01:00
Integration tests bootstrap
This commit is contained in:
parent
a8450fc309
commit
ffda64135c
8 changed files with 4803 additions and 0 deletions
103
.github/workflows/integration.yml
vendored
Normal file
103
.github/workflows/integration.yml
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
name: Integration tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable*
|
||||||
|
|
||||||
|
env:
|
||||||
|
APP_NAME: libresign
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
integration:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
php-versions: ['7.4']
|
||||||
|
databases: ['sqlite', 'mysql', 'pgsql']
|
||||||
|
server-versions: ['master']
|
||||||
|
|
||||||
|
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
ports:
|
||||||
|
- 4445:5432/tcp
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: root
|
||||||
|
POSTGRES_PASSWORD: rootpassword
|
||||||
|
POSTGRES_DB: nextcloud
|
||||||
|
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
|
||||||
|
mysql:
|
||||||
|
image: mariadb
|
||||||
|
ports:
|
||||||
|
- 4444:3306/tcp
|
||||||
|
env:
|
||||||
|
MYSQL_ROOT_PASSWORD: rootpassword
|
||||||
|
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout server
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: nextcloud/server
|
||||||
|
ref: ${{ matrix.server-versions }}
|
||||||
|
|
||||||
|
- name: Checkout submodules
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||||
|
git submodule sync --recursive
|
||||||
|
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||||
|
|
||||||
|
- name: Checkout app
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: apps/${{ env.APP_NAME }}
|
||||||
|
|
||||||
|
- name: Set up php ${{ matrix.php-versions }}
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php-versions }}
|
||||||
|
tools: phpunit
|
||||||
|
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, mysql, pdo_mysql, pgsql, pdo_pgsql,
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- name: Set up dependencies
|
||||||
|
working-directory: apps/${{ env.APP_NAME }}
|
||||||
|
run: |
|
||||||
|
composer install
|
||||||
|
composer --working-dir=tests/integration install
|
||||||
|
|
||||||
|
- name: Set up Nextcloud
|
||||||
|
run: |
|
||||||
|
if [ "${{ matrix.databases }}" = "mysql" ]; then
|
||||||
|
export DB_PORT=4444
|
||||||
|
elif [ "${{ matrix.databases }}" = "pgsql" ]; then
|
||||||
|
export DB_PORT=4445
|
||||||
|
fi
|
||||||
|
mkdir data
|
||||||
|
./occ maintenance:install \
|
||||||
|
--verbose \
|
||||||
|
--database=${{ matrix.databases }} \
|
||||||
|
--database-name=nextcloud \
|
||||||
|
--database-host=127.0.0.1 \
|
||||||
|
--database-port=$DB_PORT \
|
||||||
|
--database-user=root \
|
||||||
|
--database-pass=rootpassword \
|
||||||
|
--admin-user=admin \
|
||||||
|
--admin-pass=admin
|
||||||
|
./occ app:enable ${{ env.APP_NAME }}
|
||||||
|
php -S 0.0.0.0:8080 &
|
||||||
|
|
||||||
|
- name: Run behat
|
||||||
|
working-directory: apps/${{ env.APP_NAME }}/tests/integration
|
||||||
|
env:
|
||||||
|
TEST_SERVER_URL: http://localhost:8080/
|
||||||
|
run: |
|
||||||
|
vendor/bin/behat -f junit -f pretty
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -2,6 +2,8 @@
|
||||||
.vscode
|
.vscode
|
||||||
*.iml
|
*.iml
|
||||||
/vendor/
|
/vendor/
|
||||||
|
/tests/integration/vendor
|
||||||
|
/tests/integration/output
|
||||||
/js/
|
/js/
|
||||||
/build/
|
/build/
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
|
||||||
8
tests/integration/composer.json
Normal file
8
tests/integration/composer.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"behat/behat": "^3.10",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"guzzlehttp/guzzle": "^7.4",
|
||||||
|
"jarnaiz/behat-junit-formatter": "^1.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
4452
tests/integration/composer.lock
generated
Normal file
4452
tests/integration/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
14
tests/integration/config/behat.yml
Normal file
14
tests/integration/config/behat.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
default:
|
||||||
|
autoload:
|
||||||
|
'': '%paths.base%/../features/bootstrap'
|
||||||
|
suites:
|
||||||
|
default:
|
||||||
|
paths:
|
||||||
|
- '%paths.base%/../features'
|
||||||
|
contexts:
|
||||||
|
- FeatureContext
|
||||||
|
|
||||||
|
extensions:
|
||||||
|
jarnaiz\JUnitFormatter\JUnitFormatterExtension:
|
||||||
|
filename: report.xml
|
||||||
|
outputDir: '%paths.base%/../output/'
|
||||||
183
tests/integration/features/bootstrap/FeatureContext.php
Normal file
183
tests/integration/features/bootstrap/FeatureContext.php
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Behat\Behat\Context\Context;
|
||||||
|
use Behat\Gherkin\Node\TableNode;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Cookie\CookieJar;
|
||||||
|
use GuzzleHttp\Exception\ClientException;
|
||||||
|
use PHPUnit\Framework\Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines application features from the specific context.
|
||||||
|
*/
|
||||||
|
class FeatureContext implements Context {
|
||||||
|
public const TEST_PASSWORD = '123456';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $baseUrl;
|
||||||
|
|
||||||
|
/** @var CookieJar[] */
|
||||||
|
private $cookieJars;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $currentUser;
|
||||||
|
|
||||||
|
/** @var ResponseInterface */
|
||||||
|
private $response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes context.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->cookieJars = [];
|
||||||
|
$this->baseUrl = getenv('TEST_SERVER_URL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendOCSRequest($verb, $url, $body = null, array $headers = []) {
|
||||||
|
$url = 'ocs/v2.php' . $url;
|
||||||
|
$this->sendRequest($verb, $url, $body, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @When /^sending "([^"]*)" to "([^"]*)"( with)?$/
|
||||||
|
* @param string $verb
|
||||||
|
* @param string $url
|
||||||
|
* @param TableNode|array|null $body
|
||||||
|
* @param array $headers
|
||||||
|
*/
|
||||||
|
public function sendRequest($verb, $url, $body = null, array $headers = []) {
|
||||||
|
$url = ltrim($url, '/');
|
||||||
|
if (strpos($url, 'ocs/v2.php') === false) {
|
||||||
|
$url = 'index.php/' . $url;
|
||||||
|
}
|
||||||
|
$fullUrl = $this->baseUrl . $url;
|
||||||
|
$client = new Client();
|
||||||
|
$options = ['cookies' => $this->getUserCookieJar($this->currentUser)];
|
||||||
|
if ($this->currentUser === 'admin') {
|
||||||
|
$options['auth'] = ['admin', 'admin'];
|
||||||
|
} elseif (strpos($this->currentUser, 'guest') !== 0) {
|
||||||
|
$options['auth'] = [$this->currentUser, self::TEST_PASSWORD];
|
||||||
|
}
|
||||||
|
if ($body instanceof TableNode) {
|
||||||
|
$fd = $body->getRowsHash();
|
||||||
|
$options['form_params'] = $fd;
|
||||||
|
} elseif (is_array($body)) {
|
||||||
|
$options['form_params'] = $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options['headers'] = array_merge($headers, [
|
||||||
|
'OCS-ApiRequest' => 'true',
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->response = $client->{$verb}($fullUrl, $options);
|
||||||
|
} catch (ClientException $ex) {
|
||||||
|
$this->response = $ex->getResponse();
|
||||||
|
} catch (\GuzzleHttp\Exception\ServerException $ex) {
|
||||||
|
$this->response = $ex->getResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getUserCookieJar($user) {
|
||||||
|
if (!isset($this->cookieJars[$user])) {
|
||||||
|
$this->cookieJars[$user] = new CookieJar();
|
||||||
|
}
|
||||||
|
return $this->cookieJars[$user];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given /^user "([^"]*)" exists$/
|
||||||
|
* @param string $user
|
||||||
|
*/
|
||||||
|
public function assureUserExists($user) {
|
||||||
|
$response = $this->userExists($user);
|
||||||
|
if ($response->getStatusCode() !== 200) {
|
||||||
|
$this->createUser($user);
|
||||||
|
// Set a display name different than the user ID to be able to
|
||||||
|
// ensure in the tests that the right value was returned.
|
||||||
|
$this->setUserDisplayName($user);
|
||||||
|
$response = $this->userExists($user);
|
||||||
|
$this->assertStatusCode(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function userExists($user) {
|
||||||
|
$currentUser = $this->currentUser;
|
||||||
|
$this->setCurrentUser('admin');
|
||||||
|
$this->sendOCSRequest('GET', '/cloud/users/' . $user);
|
||||||
|
$this->setCurrentUser($currentUser);
|
||||||
|
return $this->response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createUser($user) {
|
||||||
|
$currentUser = $this->currentUser;
|
||||||
|
$this->setCurrentUser('admin');
|
||||||
|
$this->sendOCSRequest('POST', '/cloud/users', [
|
||||||
|
'userid' => $user,
|
||||||
|
'password' => self::TEST_PASSWORD,
|
||||||
|
]);
|
||||||
|
$this->assertStatusCode(200, 'Failed to create user');
|
||||||
|
|
||||||
|
//Quick hack to login once with the current user
|
||||||
|
$this->setCurrentUser($user);
|
||||||
|
$this->sendOCSRequest('GET', '/cloud/users' . '/' . $user);
|
||||||
|
$this->assertStatusCode(200, 'Failed to do first login');
|
||||||
|
|
||||||
|
$this->createdUsers[] = $user;
|
||||||
|
|
||||||
|
$this->setCurrentUser($currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Given /^as user "([^"]*)"$/
|
||||||
|
* @param string $user
|
||||||
|
*/
|
||||||
|
public function setCurrentUser($user) {
|
||||||
|
$this->currentUser = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setUserDisplayName($user) {
|
||||||
|
$currentUser = $this->currentUser;
|
||||||
|
$this->setCurrentUser('admin');
|
||||||
|
$this->sendOCSRequest('PUT', '/cloud/users/' . $user, [
|
||||||
|
'key' => 'displayname',
|
||||||
|
'value' => $user . '-displayname'
|
||||||
|
]);
|
||||||
|
$this->setCurrentUser($currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @param int $statusCode
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
protected function assertStatusCode(int $statusCode, string $message = '') {
|
||||||
|
Assert::assertEquals($statusCode, $this->response->getStatusCode(), $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then the response should have a status code :code
|
||||||
|
* @param string $code
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function theResponseShouldHaveStatusCode($code) {
|
||||||
|
$currentCode = $this->response->getStatusCode();
|
||||||
|
Assert::assertEquals($code, $currentCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Then the response should be a JSON array with the following mandatory values
|
||||||
|
* @param TableNode $table
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function theResponseShouldBeAJsonArrayWithTheFollowingMandatoryValues(TableNode $table) {
|
||||||
|
$this->response->getBody()->seek(0);
|
||||||
|
$expectedValues = $table->getColumnsHash();
|
||||||
|
$realResponseArray = json_decode($this->response->getBody()->getContents(), true);
|
||||||
|
foreach ($expectedValues as $value) {
|
||||||
|
$actualJson = json_encode($realResponseArray[$value['key']]);
|
||||||
|
Assert::assertJsonStringEqualsJsonString($value['value'], $actualJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
tests/integration/features/me.feature
Normal file
16
tests/integration/features/me.feature
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
Feature: account/me
|
||||||
|
Background: Create users
|
||||||
|
Given user "signer1" exists
|
||||||
|
|
||||||
|
Scenario: who a me with fail
|
||||||
|
Given sending "get" to "/apps/libresign/api/0.1/account/me"
|
||||||
|
Then the response should have a status code 404
|
||||||
|
|
||||||
|
Scenario: who a me with success
|
||||||
|
Given as user "signer1"
|
||||||
|
And sending "get" to "/apps/libresign/api/0.1/account/me"
|
||||||
|
Then the response should have a status code 200
|
||||||
|
And the response should be a JSON array with the following mandatory values
|
||||||
|
| key | value |
|
||||||
|
| account | {"uid":"signer1","emailAddress":null,"displayName":"signer1-displayname"} |
|
||||||
|
| settings | {"canRequestSign":false,"hasSignatureFile":false} |
|
||||||
25
tests/integration/run.sh
Executable file
25
tests/integration/run.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
APP_INTEGRATION_DIR=$PWD
|
||||||
|
ROOT_DIR=${APP_INTEGRATION_DIR}/../../../..
|
||||||
|
composer install
|
||||||
|
|
||||||
|
php -S localhost:8080 -t ${ROOT_DIR} &
|
||||||
|
PHPPID=$!
|
||||||
|
echo $PHPPID
|
||||||
|
|
||||||
|
# also kill php process in case of ctrl+c
|
||||||
|
trap 'kill -TERM $PHPPID; wait $PHPPID' TERM
|
||||||
|
|
||||||
|
${ROOT_DIR}/occ app:enable libresign || exit 1
|
||||||
|
${ROOT_DIR}/occ app:list | grep libresign
|
||||||
|
|
||||||
|
export TEST_SERVER_URL="http://localhost:8080/"
|
||||||
|
${APP_INTEGRATION_DIR}/vendor/bin/behat -f junit -f pretty $1 $2
|
||||||
|
RESULT=$?
|
||||||
|
|
||||||
|
kill $PHPPID
|
||||||
|
|
||||||
|
wait $PHPPID
|
||||||
|
|
||||||
|
exit $RESULT
|
||||||
Loading…
Add table
Reference in a new issue