diff --git a/CHANGELOG.md b/CHANGELOG.md
index a90a5def3f..91a894ac6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ You can also check [on GitHub](https://github.com/nextcloud/news/releases), the
## [25.x.x]
### Changed
- API add new field to Feed that indicates when the next update will be done "nextUpdateTime" (#2993)
+- Change logic to update feed only if the nextUpdateTime has been reached (#2999)
+- Add setting to disable the usage of nextUpdateTime (#2999)
### Fixed
- `TypeError: this.$refs.actions.$refs.menuButton is undefined` when tabbing through feeds and folders
diff --git a/appinfo/info.xml b/appinfo/info.xml
index f1493b8c0d..e3b6369a80 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -21,7 +21,7 @@ Create a [feature request](https://github.com/nextcloud/news/discussions/new)
Report a [feed issue](https://github.com/nextcloud/news/discussions/new)
]]>
-
{{ t("news", "Interval in seconds in which the feeds will be updated.") }}
+ ++ {{ t("news", "Enable this to use the calculated next update time for feed updates. Disable to update feeds based solely on the update interval.") }} +
@@ -140,6 +151,7 @@ export default { feedFetcherTimeout: loadState('news', 'feedFetcherTimeout'), exploreUrl: loadState('news', 'exploreUrl'), updateInterval: loadState('news', 'updateInterval'), + useNextUpdateTime: loadState('news', 'useNextUpdateTime') === '1', relativeTime: moment(lastCron * 1000).fromNow(), lastCron, } @@ -159,7 +171,7 @@ export default { key, }, ) - if (key === 'useCronUpdates' || key === 'purgeUnread') { + if (key === 'useCronUpdates' || key === 'purgeUnread' || key === 'useNextUpdateTime') { value = value ? '1' : '0' } try { diff --git a/tests/Unit/Service/FeedServiceTest.php b/tests/Unit/Service/FeedServiceTest.php index fa3c958bd7..3ccdb7100a 100644 --- a/tests/Unit/Service/FeedServiceTest.php +++ b/tests/Unit/Service/FeedServiceTest.php @@ -24,6 +24,7 @@ use OCA\News\Service\ItemServiceV2; use OCA\News\Utility\Time; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\IAppConfig; use OCA\News\Db\Feed; use OCA\News\Db\Item; @@ -77,6 +78,11 @@ class FeedServiceTest extends TestCase */ private $explorer; + /** + * @var \PHPUnit\Framework\MockObject\MockObject|IAppConfig + */ + private $config; + private $response; protected function setUp(): void @@ -112,14 +118,19 @@ protected function setUp(): void ->getMockBuilder(\HTMLPurifier::class) ->disableOriginalConstructor() ->getMock(); - + $this->config = $this + ->getMockBuilder(IAppConfig::class) + ->disableOriginalConstructor() + ->getMock(); + $this->class = new FeedServiceV2( $this->mapper, $this->fetcher, $this->itemService, $this->explorer, $this->purifier, - $this->logger + $this->logger, + $this->config ); $this->uid = 'jack'; } diff --git a/tests/api/feeds.bats b/tests/api/feeds.bats index add265e5bb..8a4de1d714 100644 --- a/tests/api/feeds.bats +++ b/tests/api/feeds.bats @@ -147,5 +147,6 @@ teardown() { # run is not working here. output=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$NC_FEED | jq '.feeds | .[0].nextUpdateTime') - assert_output '2071387335' -} \ No newline at end of file + # the field nextUpdateTime should be null here since the feed just got created in the DB an the items have not yet been fetched + assert_output 'null' +} diff --git a/tests/javascript/unit/components/AdminSettings.spec.ts b/tests/javascript/unit/components/AdminSettings.spec.ts index 5f0280b9ff..8d4db59c77 100644 --- a/tests/javascript/unit/components/AdminSettings.spec.ts +++ b/tests/javascript/unit/components/AdminSettings.spec.ts @@ -28,7 +28,7 @@ describe('AdminSettings.vue', () => { }) it('should initialize and fetch settings from state', () => { - expect(loadState).toBeCalledTimes(8) + expect(loadState).toBeCalledTimes(9) }) it('should send post with updated settings', async () => { diff --git a/tests/test_helper/php-feed-generator b/tests/test_helper/php-feed-generator index 99bcecc021..5323cbe365 160000 --- a/tests/test_helper/php-feed-generator +++ b/tests/test_helper/php-feed-generator @@ -1 +1 @@ -Subproject commit 99bcecc0215568f87c60c3558b4492eb25518d33 +Subproject commit 5323cbe365bcee19293ef39705afa256c1b3c1a9 diff --git a/tests/updater/update.bats b/tests/updater/update.bats index e55661bc10..5c17d97d0b 100644 --- a/tests/updater/update.bats +++ b/tests/updater/update.bats @@ -38,14 +38,17 @@ teardown() { for i in $FOLDER_IDS; do http --ignore-stdin -b -a ${user}:${APP_PASSWORD} DELETE ${BASE_URLv1}/folders/$i > /dev/null done + + # set useNextUpdateTime to true + ./occ config:app:set news useNextUpdateTime --value=true } @test "[$TESTSUITE] Test simple update" { # Create Feed FEEDID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$TEST_FEED | grep -Po '"id":\K([0-9]+)') - + sleep 2 - + # Get Items ID_LIST1=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) # Trigger Update @@ -59,47 +62,55 @@ teardown() { assert_equal "${ID_LIST1[*]}" "${ID_LIST2[*]}" } -@test "[$TESTSUITE] Test simple update with new content" { +@test "[$TESTSUITE] Test if nextUpdateTime is updated" { # Create Feed - FEEDID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$TEST_FEED | grep -Po '"id":\K([0-9]+)') - + FEED=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$TEST_FEED) + + UpdateTime1=$(echo $FEED | jq '.feeds | .[0].nextUpdateTime') + FEEDID=$(echo $FEED | jq '.feeds | .[0].id') + + assert_equal ${UpdateTime1} null + sleep 2 - - # Get Items - ID_LIST1=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) - php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 15 -s 9 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml + # Get the current time + current_time=$(date +%s) + + # Calculate the expected time range (+1 hour with some tolerance) + expected_time_min=$((current_time + 3600 - 60)) # 1 hour - 1 minute tolerance + expected_time_max=$((current_time + 3600 + 60)) # 1 hour + 1 minute tolerance + php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 15 -s 9 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml # Trigger Update http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/feeds/update userId=${user} feedId=$FEEDID - + sleep 2 - # Get Items again - ID_LIST2=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) + UpdateTime2=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/feeds | jq '.feeds | .[0].nextUpdateTime') - output="${ID_LIST2[*]}" + # Assert that UpdateTime2 is within the expected range + run bash -c "[[ $UpdateTime2 -ge $expected_time_min && $UpdateTime2 -le $expected_time_max ]]" + assert_success - # Check that they are not equal but that they match partially. - assert_not_equal "${ID_LIST1[*]}" "${ID_LIST2[*]}" - assert_output --partial "${ID_LIST1[*]}" } -@test "[$TESTSUITE] Test feed with 'outdated' items https://github.com/nextcloud/news/issues/2236 " { - # Create Feed, for the first fetch a timestamp today -1 year is used. +@test "[$TESTSUITE] Test simple update with new content" { + # Disable useNextUpdateTime + ./occ config:app:set news useNextUpdateTime --value=false + + # Create Feed FEEDID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$TEST_FEED | grep -Po '"id":\K([0-9]+)') - + sleep 2 - + # Get Items ID_LIST1=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) - # Generate Feed with older items (-o yes) - php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 15 -s 9 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml -o yes + php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 15 -s 9 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml # Trigger Update http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/feeds/update userId=${user} feedId=$FEEDID - + sleep 2 # Get Items again @@ -112,7 +123,38 @@ teardown() { assert_output --partial "${ID_LIST1[*]}" } +# older date is not a thing anymore +#@test "[$TESTSUITE] Test feed with 'outdated' items https://github.com/nextcloud/news/issues/2236 " { +# # Create Feed, for the first fetch a timestamp today -1 year is used. +# FEEDID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$TEST_FEED | grep -Po '"id":\K([0-9]+)') +# +# sleep 2 +# +# # Get Items +# ID_LIST1=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) +# +# # Generate Feed with older items (-o yes) +# php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 15 -s 9 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml -o yes +# +# # Trigger Update +# http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/feeds/update userId=${user} feedId=$FEEDID +# +# sleep 2 +# +# # Get Items again +# ID_LIST2=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) +# +# output="${ID_LIST2[*]}" +# +# # Check that they are not equal but that they match partially. +# assert_not_equal "${ID_LIST1[*]}" "${ID_LIST2[*]}" +# assert_output --partial "${ID_LIST1[*]}" +#} + @test "[$TESTSUITE] Test purge with small feed" { + # Disable useNextUpdateTime + ./occ config:app:set news useNextUpdateTime --value=false + # Generate Feed with 210 items. php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 50 -s 0 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml # Create Feed @@ -152,10 +194,10 @@ teardown() { 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}:${APP_PASSWORD} PUT ${BASE_URLv1}/feeds/$FEEDID/read newestItemId="$max" 2>&1| grep -Po '(?<=HTTP\/1\.1 )[0-9]{3}(?= OK)') - + # cleanup, purge items http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/cleanup/after-update @@ -174,13 +216,16 @@ teardown() { } @test "[$TESTSUITE] Test purge with more items than default limit 200" { + # Disable useNextUpdateTime + ./occ config:app:set news useNextUpdateTime --value=false + # Generate Feed with 210 items. php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 210 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml # Create Feed FEEDID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$TEST_FEED | grep -Po '"id":\K([0-9]+)') - + sleep 2 - + # Get Items ID_LIST=($(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/items | grep -Po '"id":\K([0-9]+)' | tr '\n' ' ')) @@ -189,10 +234,10 @@ teardown() { 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}:${APP_PASSWORD} PUT ${BASE_URLv1}/feeds/$FEEDID/read newestItemId="$max" 2>&1| grep -Po '(?<=HTTP\/1\.1 )[0-9]{3}(?= OK)') - + # cleanup, purge items http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/cleanup/after-update @@ -209,6 +254,9 @@ teardown() { } @test "[$TESTSUITE] Test Update and pruge with feed item>200; items<200" { + # Disable useNextUpdateTime + ./occ config:app:set news useNextUpdateTime --value=false + # Generate Feed with 210 items. php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 210 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/test.xml # Create Feed @@ -221,7 +269,7 @@ teardown() { 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}:${APP_PASSWORD} PUT ${BASE_URLv1}/feeds/$FEEDID/read newestItemId="$max" 2>&1| grep -Po '(?<=HTTP\/1\.1 )[0-9]{3}(?= OK)') # cleanup, purge items @@ -243,7 +291,7 @@ teardown() { 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}:${APP_PASSWORD} PUT ${BASE_URLv1}/feeds/$FEEDID/read newestItemId="$max" 2>&1| grep -Po '(?<=HTTP\/1\.1 )[0-9]{3}(?= OK)') @@ -262,11 +310,14 @@ teardown() { } @test "[$TESTSUITE] Test purge with two feeds with different item count limit" { + # Disable useNextUpdateTime + ./occ config:app:set news useNextUpdateTime --value=false + # Generate Feed with 260 items. php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 260 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/feed1.xml # Generate Feed with 210 items. php ${BATS_TEST_DIRNAME}/../test_helper/php-feed-generator/feed-generator.php -a 210 -f ${BATS_TEST_DIRNAME}/../test_helper/feeds/feed2.xml - + # Create Feeds FEED1ID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$FEED1 | grep -Po '"id":\K([0-9]+)') FEED2ID=$(http --ignore-stdin -b -a ${user}:${APP_PASSWORD} POST ${BASE_URLv1}/feeds url=$FEED2 | grep -Po '"id":\K([0-9]+)') @@ -278,11 +329,11 @@ teardown() { for n in "${ID_LIST[@]}" ; do ((n > max)) && max=$n done - + # mark all items of both feeds as read, returns nothing STATUS_CODE1=$(http --ignore-stdin -hdo /tmp/body -a ${user}:${APP_PASSWORD} PUT ${BASE_URLv1}/feeds/$FEED1ID/read newestItemId="$max" 2>&1| grep -Po '(?<=HTTP\/1\.1 )[0-9]{3}(?= OK)') STATUS_CODE2=$(http --ignore-stdin -hdo /tmp/body -a ${user}:${APP_PASSWORD} PUT ${BASE_URLv1}/feeds/$FEED2ID/read newestItemId="$max" 2>&1| grep -Po '(?<=HTTP\/1\.1 )[0-9]{3}(?= OK)') - + # cleanup, purge items http --ignore-stdin -b -a ${user}:${APP_PASSWORD} GET ${BASE_URLv1}/cleanup/after-update