2019-06-23 22:45:24 +00:00
|
|
|
<?php
|
|
|
|
/** @license MIT
|
|
|
|
* Copyright 2017 J. King, Dustin Wilson et al.
|
|
|
|
* See LICENSE and AUTHORS files for details */
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace JKingWeb\Arsse\TestCase\ImportExport;
|
|
|
|
|
2019-07-05 23:01:34 +00:00
|
|
|
use JKingWeb\Arsse\Arsse;
|
2019-06-23 22:45:24 +00:00
|
|
|
use JKingWeb\Arsse\Db\SQLite3\Driver;
|
|
|
|
use JKingWeb\Arsse\ImportExport\AbstractImportExport;
|
|
|
|
use JKingWeb\Arsse\Test\Database;
|
|
|
|
|
|
|
|
/** @covers \JKingWeb\Arsse\ImportExport\AbstractImportExport */
|
|
|
|
class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|
|
|
protected $drv;
|
|
|
|
protected $proc;
|
2019-07-05 23:01:34 +00:00
|
|
|
protected $checkTables = [
|
|
|
|
'arsse_folders' => ["id", "owner", "parent", "name"],
|
2019-07-25 17:14:29 +00:00
|
|
|
'arsse_feeds' => ["id", "url", "title"],
|
2019-07-05 23:01:34 +00:00
|
|
|
'arsse_subscriptions' => ["id", "owner", "folder", "feed", "title"],
|
|
|
|
'arsse_tags' => ["id", "owner", "name"],
|
|
|
|
'arsse_tag_members' => ["tag", "subscription", "assigned"],
|
|
|
|
];
|
2019-06-23 22:45:24 +00:00
|
|
|
|
2019-10-16 18:42:43 +00:00
|
|
|
public function setUp(): void {
|
2019-06-23 22:45:24 +00:00
|
|
|
self::clearData();
|
2019-07-05 23:01:34 +00:00
|
|
|
// create a mock user manager
|
|
|
|
Arsse::$user = \Phake::mock(\JKingWeb\Arsse\User::class);
|
2019-06-23 22:45:24 +00:00
|
|
|
// create a mock Import/Export processor
|
|
|
|
$this->proc = \Phake::partialMock(AbstractImportExport::class);
|
|
|
|
// initialize an SQLite memeory database
|
|
|
|
static::setConf();
|
|
|
|
try {
|
|
|
|
$this->drv = Driver::create();
|
|
|
|
} catch (\JKingWeb\Arsse\Db\Exception $e) {
|
|
|
|
$this->markTestSkipped("An SQLite database is required for this test");
|
|
|
|
}
|
|
|
|
// create the database interface with the suitable driver and apply the latest schema
|
|
|
|
Arsse::$db = new Database($this->drv);
|
|
|
|
Arsse::$db->driverSchemaUpdate();
|
|
|
|
$this->data = [
|
|
|
|
'arsse_users' => [
|
|
|
|
'columns' => [
|
|
|
|
'id' => 'str',
|
|
|
|
'password' => 'str',
|
2020-10-30 19:25:22 +00:00
|
|
|
'num' => 'int',
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
'rows' => [
|
2020-10-30 19:25:22 +00:00
|
|
|
["john.doe@example.com", "", 1],
|
|
|
|
["jane.doe@example.com", "", 2],
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
],
|
|
|
|
'arsse_folders' => [
|
|
|
|
'columns' => [
|
|
|
|
'id' => "int",
|
|
|
|
'owner' => "str",
|
|
|
|
'parent' => "int",
|
|
|
|
'name' => "str",
|
|
|
|
],
|
|
|
|
'rows' => [
|
2019-07-05 23:01:34 +00:00
|
|
|
[1, "john.doe@example.com", null, "Science"],
|
|
|
|
[2, "john.doe@example.com", 1, "Rocketry"],
|
|
|
|
[3, "john.doe@example.com", null, "Politics"],
|
|
|
|
[4, "john.doe@example.com", null, "Photography"],
|
|
|
|
[5, "john.doe@example.com", 3, "Local"],
|
|
|
|
[6, "john.doe@example.com", 3, "National"],
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
],
|
|
|
|
'arsse_feeds' => [
|
|
|
|
'columns' => [
|
|
|
|
'id' => "int",
|
|
|
|
'url' => "str",
|
|
|
|
'title' => "str",
|
|
|
|
],
|
|
|
|
'rows' => [
|
2019-07-05 23:01:34 +00:00
|
|
|
[1, "http://localhost:8000/Import/nasa-jpl", "NASA JPL"],
|
|
|
|
[2, "http://localhost:8000/Import/torstar", "Toronto Star"],
|
|
|
|
[3, "http://localhost:8000/Import/ars", "Ars Technica"],
|
|
|
|
[4, "http://localhost:8000/Import/cbc", "CBC News"],
|
|
|
|
[5, "http://localhost:8000/Import/citizen", "Ottawa Citizen"],
|
|
|
|
[6, "http://localhost:8000/Import/eurogamer", "Eurogamer"],
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
],
|
|
|
|
'arsse_subscriptions' => [
|
|
|
|
'columns' => [
|
|
|
|
'id' => "int",
|
|
|
|
'owner' => "str",
|
2019-07-05 23:01:34 +00:00
|
|
|
'folder' => "int",
|
2019-06-23 22:45:24 +00:00
|
|
|
'feed' => "int",
|
|
|
|
'title' => "str",
|
|
|
|
],
|
|
|
|
'rows' => [
|
2019-07-05 23:01:34 +00:00
|
|
|
[1, "john.doe@example.com", 2, 1, "NASA JPL"],
|
|
|
|
[2, "john.doe@example.com", 5, 2, "Toronto Star"],
|
|
|
|
[3, "john.doe@example.com", 1, 3, "Ars Technica"],
|
|
|
|
[4, "john.doe@example.com", 6, 4, "CBC News"],
|
|
|
|
[5, "john.doe@example.com", 6, 5, "Ottawa Citizen"],
|
|
|
|
[6, "john.doe@example.com", null, 6, "Eurogamer"],
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
],
|
|
|
|
'arsse_tags' => [
|
|
|
|
'columns' => [
|
|
|
|
'id' => "int",
|
|
|
|
'owner' => "str",
|
|
|
|
'name' => "str",
|
|
|
|
],
|
|
|
|
'rows' => [
|
2019-07-05 23:01:34 +00:00
|
|
|
[1, "john.doe@example.com", "canada"],
|
|
|
|
[2, "john.doe@example.com", "frequent"],
|
|
|
|
[3, "john.doe@example.com", "gaming"],
|
|
|
|
[4, "john.doe@example.com", "news"],
|
|
|
|
[5, "john.doe@example.com", "tech"],
|
|
|
|
[6, "john.doe@example.com", "toronto"],
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
],
|
|
|
|
'arsse_tag_members' => [
|
|
|
|
'columns' => [
|
2020-03-01 20:16:50 +00:00
|
|
|
'tag' => "int",
|
2019-06-23 22:45:24 +00:00
|
|
|
'subscription' => "int",
|
2020-03-01 20:16:50 +00:00
|
|
|
'assigned' => "bool",
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
'rows' => [
|
2019-07-05 23:01:34 +00:00
|
|
|
[1, 2, 1],
|
|
|
|
[1, 4, 1],
|
|
|
|
[1, 5, 1],
|
|
|
|
[2, 3, 1],
|
|
|
|
[2, 6, 1],
|
|
|
|
[3, 6, 1],
|
|
|
|
[4, 2, 1],
|
|
|
|
[4, 4, 1],
|
|
|
|
[4, 5, 1],
|
|
|
|
[5, 1, 1],
|
|
|
|
[5, 3, 1],
|
|
|
|
[6, 2, 1],
|
2019-06-23 22:45:24 +00:00
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
2019-07-05 23:01:34 +00:00
|
|
|
$this->primeDatabase($this->drv, $this->data);
|
2019-06-23 22:45:24 +00:00
|
|
|
}
|
|
|
|
|
2019-10-16 18:42:43 +00:00
|
|
|
public function tearDown(): void {
|
2019-06-23 22:45:24 +00:00
|
|
|
$this->drv = null;
|
|
|
|
$this->proc = null;
|
|
|
|
self::clearData();
|
|
|
|
}
|
2019-07-05 23:01:34 +00:00
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testImportForAMissingUser(): void {
|
2020-11-15 21:24:26 +00:00
|
|
|
$this->assertException("doesNotExist", "User", "ExceptionConflict");
|
2020-11-09 23:14:03 +00:00
|
|
|
$this->proc->import("no.one@example.com", "", false, false);
|
2019-07-06 01:18:30 +00:00
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testImportWithInvalidFolder(): void {
|
2019-07-06 01:18:30 +00:00
|
|
|
$in = [[
|
|
|
|
], [1 =>
|
|
|
|
['id' => 1, 'name' => "", 'parent' => 0],
|
|
|
|
]];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$this->assertException("invalidFolderName", "ImportExport");
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, false);
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testImportWithDuplicateFolder(): void {
|
2019-07-06 01:18:30 +00:00
|
|
|
$in = [[
|
|
|
|
], [1 =>
|
|
|
|
['id' => 1, 'name' => "New", 'parent' => 0],
|
|
|
|
['id' => 2, 'name' => "New", 'parent' => 0],
|
|
|
|
]];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$this->assertException("invalidFolderCopy", "ImportExport");
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, false);
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testMakeNoEffectiveChanges(): void {
|
2019-07-05 23:01:34 +00:00
|
|
|
$in = [[
|
|
|
|
['url' => "http://localhost:8000/Import/nasa-jpl", 'title' => "NASA JPL", 'folder' => 3, 'tags' => ["tech"]],
|
|
|
|
['url' => "http://localhost:8000/Import/ars", 'title' => "Ars Technica", 'folder' => 2, 'tags' => ["frequent", "tech"]],
|
|
|
|
['url' => "http://localhost:8000/Import/torstar", 'title' => "Toronto Star", 'folder' => 5, 'tags' => ["news", "canada", "toronto"]],
|
|
|
|
['url' => "http://localhost:8000/Import/citizen", 'title' => "Ottawa Citizen", 'folder' => 6, 'tags' => ["news", "canada"]],
|
|
|
|
['url' => "http://localhost:8000/Import/eurogamer", 'title' => "Eurogamer", 'folder' => 0, 'tags' => ["gaming", "frequent"]],
|
|
|
|
['url' => "http://localhost:8000/Import/cbc", 'title' => "CBC News", 'folder' => 6, 'tags' => ["news", "canada"]],
|
2020-03-01 20:16:50 +00:00
|
|
|
], [1 =>
|
2019-07-05 23:01:34 +00:00
|
|
|
['id' => 1, 'name' => "Photography", 'parent' => 0],
|
|
|
|
['id' => 2, 'name' => "Science", 'parent' => 0],
|
|
|
|
['id' => 3, 'name' => "Rocketry", 'parent' => 2],
|
|
|
|
['id' => 4, 'name' => "Politics", 'parent' => 0],
|
|
|
|
['id' => 5, 'name' => "Local", 'parent' => 4],
|
|
|
|
['id' => 6, 'name' => "National", 'parent' => 4],
|
|
|
|
]];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$exp = $this->primeExpectations($this->data, $this->checkTables);
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, false);
|
|
|
|
$this->compareExpectations($this->drv, $exp);
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, true);
|
|
|
|
$this->compareExpectations($this->drv, $exp);
|
|
|
|
}
|
2019-07-25 17:14:29 +00:00
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testModifyASubscription(): void {
|
2019-07-25 17:14:29 +00:00
|
|
|
$in = [[
|
|
|
|
['url' => "http://localhost:8000/Import/nasa-jpl", 'title' => "NASA JPL", 'folder' => 3, 'tags' => ["tech"]],
|
|
|
|
['url' => "http://localhost:8000/Import/ars", 'title' => "Ars Technica", 'folder' => 2, 'tags' => ["frequent", "tech"]],
|
|
|
|
['url' => "http://localhost:8000/Import/torstar", 'title' => "Toronto Star", 'folder' => 5, 'tags' => ["news", "canada", "toronto"]],
|
|
|
|
['url' => "http://localhost:8000/Import/citizen", 'title' => "Ottawa Citizen", 'folder' => 6, 'tags' => ["news", "canada"]],
|
|
|
|
['url' => "http://localhost:8000/Import/eurogamer", 'title' => "Eurogamer", 'folder' => 0, 'tags' => ["gaming", "frequent"]],
|
|
|
|
['url' => "http://localhost:8000/Import/cbc", 'title' => "CBC", 'folder' => 0, 'tags' => ["news", "canada"]], // moved to root and renamed
|
2020-03-01 20:16:50 +00:00
|
|
|
], [1 =>
|
2019-07-25 17:14:29 +00:00
|
|
|
['id' => 1, 'name' => "Photography", 'parent' => 0],
|
|
|
|
['id' => 2, 'name' => "Science", 'parent' => 0],
|
|
|
|
['id' => 3, 'name' => "Rocketry", 'parent' => 2],
|
|
|
|
['id' => 4, 'name' => "Politics", 'parent' => 0],
|
|
|
|
['id' => 5, 'name' => "Local", 'parent' => 4],
|
|
|
|
['id' => 6, 'name' => "National", 'parent' => 4],
|
2019-10-17 17:00:56 +00:00
|
|
|
['id' => 7, 'name' => "Nature", 'parent' => 0], // new folder
|
2019-07-25 17:14:29 +00:00
|
|
|
]];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, true);
|
|
|
|
$exp = $this->primeExpectations($this->data, $this->checkTables);
|
|
|
|
$exp['arsse_subscriptions']['rows'][3] = [4, "john.doe@example.com", null, 4, "CBC"];
|
2019-10-17 17:00:56 +00:00
|
|
|
$exp['arsse_folders']['rows'][] = [7, "john.doe@example.com", null, "Nature"];
|
2019-07-25 17:14:29 +00:00
|
|
|
$this->compareExpectations($this->drv, $exp);
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testImportAFeed(): void {
|
2019-07-25 17:14:29 +00:00
|
|
|
$in = [[
|
|
|
|
['url' => "http://localhost:8000/Import/some-feed", 'title' => "Some Feed", 'folder' => 0, 'tags' => ["frequent", "cryptic"]], //one existing tag and one new one
|
|
|
|
], []];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, false);
|
|
|
|
$exp = $this->primeExpectations($this->data, $this->checkTables);
|
|
|
|
$exp['arsse_feeds']['rows'][] = [7, "http://localhost:8000/Import/some-feed", "Some feed"]; // author-supplied and user-supplied titles differ
|
|
|
|
$exp['arsse_subscriptions']['rows'][] = [7, "john.doe@example.com", null, 7, "Some Feed"];
|
|
|
|
$exp['arsse_tags']['rows'][] = [7, "john.doe@example.com", "cryptic"];
|
|
|
|
$exp['arsse_tag_members']['rows'][] = [2, 7, 1];
|
|
|
|
$exp['arsse_tag_members']['rows'][] = [7, 7, 1];
|
|
|
|
$this->compareExpectations($this->drv, $exp);
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testImportAFeedWithAnInvalidTag(): void {
|
2019-07-25 17:14:29 +00:00
|
|
|
$in = [[
|
|
|
|
['url' => "http://localhost:8000/Import/some-feed", 'title' => "Some Feed", 'folder' => 0, 'tags' => [""]],
|
|
|
|
], []];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$this->assertException("invalidTagName", "ImportExport");
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, false);
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testReplaceData(): void {
|
2019-07-25 17:14:29 +00:00
|
|
|
$in = [[
|
|
|
|
['url' => "http://localhost:8000/Import/some-feed", 'title' => "Some Feed", 'folder' => 1, 'tags' => ["frequent", "cryptic"]],
|
|
|
|
], [1 =>
|
|
|
|
['id' => 1, 'name' => "Photography", 'parent' => 0],
|
|
|
|
]];
|
|
|
|
\Phake::when($this->proc)->parse->thenReturn($in);
|
|
|
|
$this->proc->import("john.doe@example.com", "", false, true);
|
|
|
|
$exp = $this->primeExpectations($this->data, $this->checkTables);
|
|
|
|
$exp['arsse_feeds']['rows'][] = [7, "http://localhost:8000/Import/some-feed", "Some feed"]; // author-supplied and user-supplied titles differ
|
|
|
|
$exp['arsse_subscriptions']['rows'] = [[7, "john.doe@example.com", 4, 7, "Some Feed"]];
|
|
|
|
$exp['arsse_tags']['rows'] = [[2, "john.doe@example.com", "frequent"], [7, "john.doe@example.com", "cryptic"]];
|
|
|
|
$exp['arsse_tag_members']['rows'] = [[2, 7, 1], [7, 7, 1]];
|
|
|
|
$exp['arsse_folders']['rows'] = [[4, "john.doe@example.com", null, "Photography"]];
|
|
|
|
$this->compareExpectations($this->drv, $exp);
|
|
|
|
}
|
2019-06-23 22:45:24 +00:00
|
|
|
}
|