From eca96ad37d89b442ae4e0463ec8f7a5bee3007f1 Mon Sep 17 00:00:00 2001 From: Benjamin Brahmer <info@b-brahmer.de> Date: Sun, 29 May 2022 11:25:38 +0200 Subject: [PATCH] Enable API testing (#1699) Enable API testing with local php server. This adds many tests for API v1.2, more still possible. Which increased the quality of news already. Signed-off-by: Benjamin Brahmer <info@b-brahmer.de> --- .github/workflows/api-integration-tests.yml | 24 ++- .gitignore | 3 + .gitmodules | 6 + tests/api/feeds.bats | 137 ++++++++++++++++++ tests/api/folders.bats | 89 ++++++++++++ tests/api/helpers/settings.bash | 4 + tests/api/items.bats | 66 +++++++++ tests/{integration => command}/explore.bats | 0 tests/{integration => command}/feeds.bats | 0 tests/{integration => command}/folders.bats | 0 .../helpers/settings.bash | 0 tests/{integration => command}/items.bats | 0 tests/{integration => command}/opml.bats | 0 tests/test_helper/bats-assert | 1 + tests/test_helper/bats-support | 1 + 15 files changed, 326 insertions(+), 5 deletions(-) create mode 100644 .gitmodules create mode 100644 tests/api/feeds.bats create mode 100644 tests/api/folders.bats create mode 100644 tests/api/helpers/settings.bash create mode 100644 tests/api/items.bats rename tests/{integration => command}/explore.bats (100%) rename tests/{integration => command}/feeds.bats (100%) rename tests/{integration => command}/folders.bats (100%) rename tests/{integration => command}/helpers/settings.bash (100%) rename tests/{integration => command}/items.bats (100%) rename tests/{integration => command}/opml.bats (100%) create mode 160000 tests/test_helper/bats-assert create mode 160000 tests/test_helper/bats-support diff --git a/.github/workflows/api-integration-tests.yml b/.github/workflows/api-integration-tests.yml index c9a1d4cc9..117e7af49 100644 --- a/.github/workflows/api-integration-tests.yml +++ b/.github/workflows/api-integration-tests.yml @@ -33,11 +33,11 @@ jobs: database: ['sqlite', 'pgsql', 'mysql'] experimental: [false] include: - - php-versions: 8.0 + - php-versions: '8.0' nextcloud: pre-release database: sqlite experimental: true - - php-versions: 8.1 + - php-versions: '8.1' nextcloud: pre-release database: sqlite experimental: true @@ -48,6 +48,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -56,8 +58,8 @@ jobs: extensions: pdo_sqlite,pdo_mysql,pdo_pgsql,gd,zip coverage: none - - name: Setup BATS - uses: mig4/setup-bats@v1.2.0 + - name: Setup BATS & httpie + run: sudo apt-get install -y bats httpie ### MySQL specific setup - name: Setup mysql @@ -108,6 +110,17 @@ jobs: check-code: false force: ${{ matrix.experimental }} + - name: Run API tests + working-directory: ../server + run: | + php -S localhost:8080 &> /tmp/webserver.log & + sleep 2 + + bats apps/news/tests/api + + # Kill php server + kill %1 + - name: Setup problem matchers for PHP run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" @@ -118,7 +131,7 @@ jobs: - name: Functional tests working-directory: ../server - run: bats apps/news/tests/integration + run: bats apps/news/tests/command - name: Prep PHP tests working-directory: ../server/apps/news @@ -127,3 +140,4 @@ jobs: - name: Feed tests working-directory: ../server/apps/news run: make feed-test + diff --git a/.gitignore b/.gitignore index 44cf6f335..7f9ed3550 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ js/*.xml .phpunit.result.cache site/ +#bats +tests/api/helpers/settings-override.bash + # python PKG-INFO *pyc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d74af0778 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "tests/test_helper/bats-support"] + path = tests/test_helper/bats-support + url = https://github.com/bats-core/bats-support.git +[submodule "tests/test_helper/bats-assert"] + path = tests/test_helper/bats-assert + url = https://github.com/bats-core/bats-assert.git diff --git a/tests/api/feeds.bats b/tests/api/feeds.bats new file mode 100644 index 000000000..054fd776a --- /dev/null +++ b/tests/api/feeds.bats @@ -0,0 +1,137 @@ +#!/usr/bin/env bats + +setup() { + load "../test_helper/bats-support/load" + load "../test_helper/bats-assert/load" + load "helpers/settings" + + if test -f "tests/api/helpers/settings-override.bash"; then + load "helpers/settings-override" + fi +} + +TESTSUITE="Feeds" + +teardown() { + # delete all feeds + ID_LIST=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + for i in $ID_LIST; do + http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/feeds/$i + done + + # delete all folders + ID_LIST=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/folders | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + for i in $ID_LIST; do + http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/folders/$i + done +} + +@test "[$TESTSUITE] Read empty" { + run http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds + + assert_output --partial "\"feeds\":[]" + assert_output --partial "\"starredCount\":0" +} + +@test "[$TESTSUITE] Create new" { + # run is not working here. + output=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED | jq '.feeds | .[0].url') + + # self reference of feed is used here + assert_output '"https://nextcloud.com/feed/"' +} + +@test "[$TESTSUITE] Create new inside folder" { + # create folder and store id + ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + + # run is not working here. + output=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED folderId=$ID | jq '.feeds | .[0].folderId') + + # check if ID matches + assert_output "$ID" +} + +@test "[$TESTSUITE] Delete one" { + ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED | grep -Po '"id":\K([0-9]+)') + + run http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/feeds/$ID + + assert_output "[]" +} + +@test "[$TESTSUITE] Move feed to different folder" { + # create folders and store ids + FIRST_FOLDER_ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + SECCOND_FOLDER_ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + + FEEDID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED folderId=$FIRST_FOLDER_ID | grep -Po '"id":\K([0-9]+)') + + # move feed, returns nothing + http --ignore-stdin -b -a ${user}:${user} PUT ${BASE_URLv1}/feeds/$FEEDID/move folderId=$SECCOND_FOLDER_ID + + # run is not working here. + output=$(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds | jq '.feeds | .[0].folderId') + + # look for second folder id + assert_output "$SECCOND_FOLDER_ID" +} + +@test "[$TESTSUITE] Move feed to root" { + # create folder and store id + FOLDER_ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + + FEEDID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED folderId=$FOLDER_ID | grep -Po '"id":\K([0-9]+)') + + # move feed to "null", returns nothing + http --ignore-stdin -b -a ${user}:${user} PUT ${BASE_URLv1}/feeds/$FEEDID/move folderId=null + + # run is not working here. + output=$(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds | jq '.feeds | .[0].folderId') + + # new "folder" should be null + assert_output null +} + +@test "[$TESTSUITE] Rename feed" { + # create feed and store id + FEEDID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED | grep -Po '"id":\K([0-9]+)') + + # rename feed, returns nothing + http --ignore-stdin -b -a ${user}:${user} PUT ${BASE_URLv1}/feeds/$FEEDID/rename feedTitle="Great Title" + + # run is not working here. + output=$(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds | jq '.feeds | .[0].title') + + # Check if title matches + assert_output '"Great Title"' +} + +@test "[$TESTSUITE] Mark all items as read" { + # create feed and store id + FEEDID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED | grep -Po '"id":\K([0-9]+)') + + ID_LIST=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items id=$FEEDID | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + + # get biggest item ID + max=${ID_LIST[0]} + for n in "${ID_LIST[@]}" ; do + ((n > max)) && max=$n + done + + # mark all items of feed as read, returns nothing + STATUS_CODE=$(http --ignore-stdin -hdo /tmp/body -a ${user}:${user} PUT ${BASE_URLv1}/feeds/$FEEDID/read newestItemId="$max" 2>&1| grep HTTP/) + + # collect unread status + unread=$(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items id=$FEEDID | grep -Po '"unread":\K((true)|(false))' | tr '\n' ' ') + + for n in "${unread[@]}" ; do + if $n + then + echo "Item was not marked as read" + echo $STATUS_CODE + false + fi + done +} + diff --git a/tests/api/folders.bats b/tests/api/folders.bats new file mode 100644 index 000000000..710b7d2a3 --- /dev/null +++ b/tests/api/folders.bats @@ -0,0 +1,89 @@ +#!/usr/bin/env bats + +setup() { + load "../test_helper/bats-support/load" + load "../test_helper/bats-assert/load" + load "helpers/settings" + + if test -f "tests/api/helpers/settings-override.bash"; then + load "helpers/settings-override" + fi + +} + +TESTSUITE="Folders" + +teardown() { + # delete all feeds + FEED_IDS=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + for i in $FEED_IDS; do + http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/feeds/$i + done + + # delete all folders + FOLDER_IDS=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/folders | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + for i in $FOLDER_IDS; do + http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/folders/$i + done +} + +@test "[$TESTSUITE] Read empty" { + run http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/folders + + assert_output --partial "\"folders\":[]" +} + +@test "[$TESTSUITE] Create new" { + run http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} + + assert_output --partial "\"name\":\"news-${BATS_SUITE_TEST_NUMBER}\"," +} + +@test "[$TESTSUITE] Delete folder" { + ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + + run http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/folders/$ID + + assert_output "[]" +} + +@test "[$TESTSUITE] Rename folder" { + ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + + # Rename folder + http --ignore-stdin -b -a ${user}:${user} PUT ${BASE_URLv1}/folders/$ID name=rename-${BATS_SUITE_TEST_NUMBER} + + run http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/folders + + assert_output --partial "\"name\":\"rename-${BATS_SUITE_TEST_NUMBER}\"," +} + +@test "[$TESTSUITE] Mark all items as read" { + # create folder and feed in folder + FOLDER_ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/folders name=news-${BATS_SUITE_TEST_NUMBER} | grep -Po '"id":\K([0-9]+)') + FEED_ID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED folderId=$FOLDER_ID | grep -Po '"id":\K([0-9]+)') + + ID_LIST=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items id=$FEEDID | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + + # get biggest item ID + max=${ID_LIST[0]} + for n in "${ID_LIST[@]}" ; do + ((n > max)) && max=$n + done + + # mark all items of feed as read, returns nothing + STATUS_CODE=$(http --ignore-stdin -hdo /tmp/body -a ${user}:${user} PUT ${BASE_URLv1}/folders/$FOLDER_ID/read newestItemId="$max" 2>&1| grep HTTP/) + + # collect unread status + unread=$(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items id=$FEEDID | grep -Po '"unread":\K((true)|(false))' | tr '\n' ' ') + + for n in "${unread[@]}" ; do + if $n + then + echo "Item was not marked as read" + echo $STATUS_CODE + false + fi + done +} + diff --git a/tests/api/helpers/settings.bash b/tests/api/helpers/settings.bash new file mode 100644 index 000000000..3b31fba4c --- /dev/null +++ b/tests/api/helpers/settings.bash @@ -0,0 +1,4 @@ +user=admin +NC_FEED="https://nextcloud.com/blog/static-feed/" +HEISE_FEED="https://www.heise.de/rss/heise-atom.xml" +BASE_URLv1="http://localhost:8080/index.php/apps/news/api/v1-2" \ No newline at end of file diff --git a/tests/api/items.bats b/tests/api/items.bats new file mode 100644 index 000000000..349678966 --- /dev/null +++ b/tests/api/items.bats @@ -0,0 +1,66 @@ +#!/usr/bin/env bats + +setup() { + load "../test_helper/bats-support/load" + load "../test_helper/bats-assert/load" + load "helpers/settings" + + if test -f "tests/api/helpers/settings-override.bash"; then + load "helpers/settings-override" + fi +} + +TESTSUITE="Items" + +teardown() { + # delete all feeds + FEED_IDS=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/feeds | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + for i in $FEED_IDS; do + http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/feeds/$i + done + + # delete all folders + FOLDER_IDS=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/folders | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + for i in $FOLDER_IDS; do + http --ignore-stdin -b -a ${user}:${user} DELETE ${BASE_URLv1}/folders/$i + done +} + +@test "[$TESTSUITE] Read empty" { + run http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items + + assert_output --partial "\"items\":[]" +} + +@test "[$TESTSUITE] Read 5" { + http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED + + ID_LIST=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items batchSize=5 | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + + output=${#ID_LIST[@]} + + assert_output --partial "5" +} + +# TODO GET /items has more options that could be tested. + +@test "[$TESTSUITE] Check updated" { + FEEDID=$(http --ignore-stdin -b -a ${user}:${user} POST ${BASE_URLv1}/feeds url=$NC_FEED | grep -Po '"id":\K([0-9]+)') + ID_LIST=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items id=$FEEDID | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + + # get biggest item ID + max=${ID_LIST[0]} + for n in "${ID_LIST[@]}" ; do + ((n > max)) && max=$n + done + + SYNC_TIME=$(date +%s) + + # mark all items of feed as read, returns nothing (other client marks items as read) + STATUS_CODE=$(http --ignore-stdin -hdo /tmp/body -a ${user}:${user} PUT ${BASE_URLv1}/feeds/$FEEDID/read newestItemId="$max" 2>&1| grep HTTP/) + + # client 2 checks for updates since last sync + UPDATED_ITEMS=($(http --ignore-stdin -b -a ${user}:${user} GET ${BASE_URLv1}/items/updated id=$FEEDID lastModified=$SYNC_TIME | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + + assert_equal ${#ID_LIST[@]} ${#UPDATED_ITEMS[@]} +} \ No newline at end of file diff --git a/tests/integration/explore.bats b/tests/command/explore.bats similarity index 100% rename from tests/integration/explore.bats rename to tests/command/explore.bats diff --git a/tests/integration/feeds.bats b/tests/command/feeds.bats similarity index 100% rename from tests/integration/feeds.bats rename to tests/command/feeds.bats diff --git a/tests/integration/folders.bats b/tests/command/folders.bats similarity index 100% rename from tests/integration/folders.bats rename to tests/command/folders.bats diff --git a/tests/integration/helpers/settings.bash b/tests/command/helpers/settings.bash similarity index 100% rename from tests/integration/helpers/settings.bash rename to tests/command/helpers/settings.bash diff --git a/tests/integration/items.bats b/tests/command/items.bats similarity index 100% rename from tests/integration/items.bats rename to tests/command/items.bats diff --git a/tests/integration/opml.bats b/tests/command/opml.bats similarity index 100% rename from tests/integration/opml.bats rename to tests/command/opml.bats diff --git a/tests/test_helper/bats-assert b/tests/test_helper/bats-assert new file mode 160000 index 000000000..397c73521 --- /dev/null +++ b/tests/test_helper/bats-assert @@ -0,0 +1 @@ +Subproject commit 397c735212bf1a06cfdd0cb7806c5a6ea79582bf diff --git a/tests/test_helper/bats-support b/tests/test_helper/bats-support new file mode 160000 index 000000000..3c8fadc50 --- /dev/null +++ b/tests/test_helper/bats-support @@ -0,0 +1 @@ +Subproject commit 3c8fadc5097c9acfc96d836dced2bb598e48b009