mirror of
https://github.com/photoprism/photoprism.git
synced 2026-01-23 02:24:24 +00:00
Frontend: Improve acceptance test performance #5298
* Tests: improve openNav, and add ability to close all event notifications. * Tests: improve search with wait for notifications to expire, then using notifications to determine search completion. * Tests: improve getPhotoCount by using notifications for completion of photo load. Add fast and slow photo load waits. * Tests: add fast and slow load detection via notifications * Tests: replace waits with notification detection * Tests: refactor tests to work more efficiently with notifications * Tests: comment out execution time and p-notify__close logging. Remove slow version of waits. * Make: allow acceptance tests to be run with --ignore-errors, and make each multi window test run as separate instance * Frontend: ensure that closing a notification resets the timer for the next notification * Tests: move notification handling to single notifications.js file * Tests: move photoCount as changing cards view doesn't generate event when there is one photo * Tests: remove commented code * Tests: enable environment variable SHOW_LOGS (true) to show timings and click actions for waits * Tests: add Delete, Import, Index, Unstack, and Upload notification waits.
This commit is contained in:
parent
5afb634edf
commit
6d0016b1df
14 changed files with 268 additions and 77 deletions
12
Makefile
12
Makefile
|
|
@ -364,16 +364,20 @@ test-js:
|
|||
(cd frontend && npm run test)
|
||||
acceptance:
|
||||
$(info Running public-mode tests in Chrome...)
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Multi-Window)\:*" --test-meta mode=public --config-file ./testcaferc.json --experimental-multiple-windows "tests/acceptance" && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=public --config-file ./testcaferc.json "tests/acceptance")
|
||||
(cd frontend && find ./tests/acceptance -type f -name "*.js" | xargs -i perl -0777 -ne 'while(/(?:mode: \"auth[^,]*\,)|(Multi-Window\:[A-Za-z 0-9\-_]*)/g){print "$$1\n" if ($$1);}' {} | xargs -I testname bash -c 'npm run testcafe -- "chrome --headless=new" --experimental-multiple-windows --test-meta mode=public --config-file ./testcaferc.json --test "testname" "tests/acceptance"')
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=public --config-file ./testcaferc.json "tests/acceptance")
|
||||
acceptance-short:
|
||||
$(info Running JS acceptance tests in Chrome...)
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Multi-Window)\:*" --test-meta mode=public --config-file ./testcaferc.json --experimental-multiple-windows "tests/acceptance" && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=public,type=short --config-file ./testcaferc.json "tests/acceptance")
|
||||
(cd frontend && find ./tests/acceptance -type f -name "*.js" | xargs -i perl -0777 -ne 'while(/(?:mode: \"auth[^,]*\,)|(Multi-Window\:[A-Za-z 0-9\-_]*)/g){print "$$1\n" if ($$1);}' {} | xargs -I testname bash -c 'npm run testcafe -- "chrome --headless=new" --experimental-multiple-windows --test-meta mode=public,type=short --config-file ./testcaferc.json --test "testname" "tests/acceptance"')
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=public,type=short --config-file ./testcaferc.json "tests/acceptance")
|
||||
acceptance-auth:
|
||||
$(info Running JS acceptance-auth tests in Chrome...)
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Multi-Window)\:*" --test-meta mode=auth --config-file ./testcaferc.json --experimental-multiple-windows "tests/acceptance" && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=auth --config-file ./testcaferc.json "tests/acceptance")
|
||||
(cd frontend && find ./tests/acceptance -type f -name "*.js" | xargs -i perl -0777 -ne 'while(/(?:mode: \"public[^,]*\,)|(Multi-Window\:[A-Za-z 0-9\-_]*)/g){print "$$1\n" if ($$1);}' {} | xargs -I testname bash -c 'npm run testcafe -- "chrome --headless=new" --experimental-multiple-windows --test-meta mode=auth --config-file ./testcaferc.json --test "testname" "tests/acceptance"')
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=auth --config-file ./testcaferc.json "tests/acceptance")
|
||||
acceptance-auth-short:
|
||||
$(info Running JS acceptance-auth tests in Chrome...)
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Multi-Window)\:*" --test-meta mode=auth --config-file ./testcaferc.json --experimental-multiple-windows "tests/acceptance" && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=auth,type=short --config-file ./testcaferc.json "tests/acceptance")
|
||||
(cd frontend && find ./tests/acceptance -type f -name "*.js" | xargs -i perl -0777 -ne 'while(/(?:mode: \"public[^,]*\,)|(Multi-Window\:[A-Za-z 0-9\-_]*)/g){print "$$1\n" if ($$1);}' {} | xargs -I testname bash -c 'npm run testcafe -- "chrome --headless=new" --experimental-multiple-windows --test-meta mode=auth,type=short --config-file ./testcaferc.json --test "testname" "tests/acceptance"')
|
||||
(cd frontend && npm run testcafe -- "chrome --headless=new" --test-grep "^(Common|Core)\:*" --test-meta mode=auth,type=short --config-file ./testcaferc.json "tests/acceptance")
|
||||
vitest-watch:
|
||||
$(info Running Vitest unit tests in watch mode...)
|
||||
(cd frontend && npm run test-watch)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export default {
|
|||
color: "transparent",
|
||||
text: "",
|
||||
delay: this.defaultDelay,
|
||||
timer: 0,
|
||||
},
|
||||
lastText: "",
|
||||
lastId: 1,
|
||||
|
|
@ -127,6 +128,7 @@ export default {
|
|||
|
||||
this.lastId++;
|
||||
this.lastText = text;
|
||||
let timer = 0;
|
||||
|
||||
const m = {
|
||||
id: this.lastId,
|
||||
|
|
@ -134,6 +136,7 @@ export default {
|
|||
icon,
|
||||
text,
|
||||
delay,
|
||||
timer,
|
||||
};
|
||||
|
||||
this.messages.push(m);
|
||||
|
|
@ -144,6 +147,9 @@ export default {
|
|||
},
|
||||
showNext() {
|
||||
const message = this.messages.shift();
|
||||
if (this.message.timer > 0) {
|
||||
clearTimeout(this.message.timer);
|
||||
};
|
||||
|
||||
if (message) {
|
||||
this.message = message;
|
||||
|
|
@ -166,14 +172,16 @@ export default {
|
|||
|
||||
this.visible = true;
|
||||
|
||||
setTimeout(() => {
|
||||
this.message.timer = setTimeout(() => {
|
||||
this.lastText = "";
|
||||
this.message.timer = 0;
|
||||
this.showNext();
|
||||
}, this.message.delay);
|
||||
} else {
|
||||
this.lastText = "";
|
||||
this.visible = false;
|
||||
this.message.text = "";
|
||||
this.message.timer = 0;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import PhotoViewer from "../page-model/photoviewer";
|
|||
import Page from "../page-model/page";
|
||||
import AlbumDialog from "../page-model/dialog-album";
|
||||
import PhotoEdit from "../page-model/photo-edit";
|
||||
import Notifies from "../page-model/notifications";
|
||||
|
||||
fixture`Test albums`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ const photoviewer = new PhotoViewer();
|
|||
const page = new Page();
|
||||
const albumdialog = new AlbumDialog();
|
||||
const photoedit = new PhotoEdit();
|
||||
const notifies = new Notifies();
|
||||
|
||||
test.meta("testID", "albums-001").meta({ type: "short", mode: "public" })(
|
||||
"Common: Create/delete album on /albums",
|
||||
|
|
@ -152,6 +154,7 @@ test.meta("testID", "albums-004").meta({ type: "short", mode: "public" })(
|
|||
async (t) => {
|
||||
// Get initial counts for both Holiday and Christmas albums
|
||||
await menu.openPage("albums");
|
||||
await notifies.waitForPhotosToLoad(2000);
|
||||
await toolbar.search("Holiday");
|
||||
const HolidayAlbumUid = await album.getNthAlbumUid("all", 0);
|
||||
await album.openAlbumWithUid(HolidayAlbumUid);
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ test.meta("testID", "labels-003").meta({ mode: "public" })("Common: Rename Label
|
|||
await toolbar.search("zebra");
|
||||
const LabelZebraUid = await label.getNthLabeltUid(0);
|
||||
await label.openNthLabel(0);
|
||||
const FirstPhotoZebraUid = await photo.getNthPhotoUid("all", 0);
|
||||
const PhotoCountZebra = await photo.getPhotoCount("all");
|
||||
const FirstPhotoZebraUid = await photo.getNthPhotoUid("all", 0);
|
||||
await menu.openPage("labels");
|
||||
await toolbar.search("zebra");
|
||||
await t
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import Menu from "../../page-model/menu";
|
|||
import Toolbar from "../../page-model/toolbar";
|
||||
import Page from "../../page-model/page";
|
||||
import Library from "../../page-model/library";
|
||||
import Notifies from "../../page-model/notifications";
|
||||
|
||||
fixture`Import file from folder`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -11,6 +12,7 @@ const menu = new Menu();
|
|||
const toolbar = new Toolbar();
|
||||
const page = new Page();
|
||||
const library = new Library();
|
||||
const notifies = new Notifies();
|
||||
|
||||
test.meta("testID", "library-import-001").meta({ type: "short", mode: "public" })(
|
||||
"Common: Import files from folder using copy",
|
||||
|
|
@ -27,9 +29,8 @@ test.meta("testID", "library-import-001").meta({ type: "short", mode: "public" }
|
|||
.wait(9000)
|
||||
.typeText(library.openImportFolderSelect, "/Bäcke", { replace: true })
|
||||
.click(page.selectOption.nth(0))
|
||||
.click(library.import)
|
||||
//TODO replace wait
|
||||
.wait(60000);
|
||||
.click(library.import);
|
||||
await notifies.waitForImport(60000);
|
||||
await menu.openPage("labels");
|
||||
if (t.browser.platform === "mobile") {
|
||||
await t.eval(() => location.reload());
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import Photo from "../../page-model/photo";
|
|||
import Page from "../../page-model/page";
|
||||
import Library from "../../page-model/library";
|
||||
import Album from "../../page-model/album";
|
||||
import Notifies from "../../page-model/notifications";
|
||||
|
||||
fixture`Test index`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ const photo = new Photo();
|
|||
const page = new Page();
|
||||
const library = new Library();
|
||||
const album = new Album();
|
||||
const notifies = new Notifies();
|
||||
|
||||
test.meta("testID", "library-index-001").meta({ type: "short", mode: "public" })(
|
||||
"Common: Index files from folder",
|
||||
|
|
@ -66,9 +68,8 @@ test.meta("testID", "library-index-001").meta({ type: "short", mode: "public" })
|
|||
.click(library.indexFolderSelect)
|
||||
.typeText(library.indexFolderSelect, "/mo", { replace: true })
|
||||
.click(page.selectOption.withText("/moment"))
|
||||
.click(library.index)
|
||||
//TODO replace wait
|
||||
.wait(50000);
|
||||
.click(library.index);
|
||||
await notifies.waitForIndexing(50000);
|
||||
|
||||
await t.expect(Selector("span").withText("Done.").visible, { timeout: 60000 }).ok();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import ContextMenu from "../page-model/context-menu";
|
|||
import Photo from "../page-model/photo";
|
||||
import Subject from "../page-model/subject";
|
||||
import PhotoEdit from "../page-model/photo-edit";
|
||||
import Notifies from "../page-model/notifications";
|
||||
|
||||
fixture`Test people`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ const contextmenu = new ContextMenu();
|
|||
const photo = new Photo();
|
||||
const subject = new Subject();
|
||||
const photoedit = new PhotoEdit();
|
||||
const notifies = new Notifies();
|
||||
|
||||
test.meta("testID", "people-001").meta({ type: "short", mode: "public" })(
|
||||
"Common: Add name to new face and rename subject",
|
||||
|
|
@ -41,8 +43,9 @@ test.meta("testID", "people-001").meta({ type: "short", mode: "public" })(
|
|||
|
||||
await t.click(subject.recognizedTab);
|
||||
await subject.checkFaceVisibility(FirstFaceID, false);
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(6000);
|
||||
await notifies.waitForPeopleToLoad(6000, true);
|
||||
const SubjectCountAfterAdd = await subject.getSubjectCount();
|
||||
|
||||
await t.expect(SubjectCountAfterAdd).eql(SubjectCount + 1);
|
||||
|
|
@ -92,7 +95,7 @@ test.meta("testID", "people-001").meta({ type: "short", mode: "public" })(
|
|||
await t.expect(photoedit.inputName.nth(0).value).contains("Max Mu").click(photoedit.dialogClose);
|
||||
|
||||
await contextmenu.clearSelection();
|
||||
await toolbar.search("person:max-mu");
|
||||
await toolbar.search("person:max-mu", false);
|
||||
const PhotosInSubjectAfterRenameCount = await photo.getPhotoCount("all");
|
||||
await t.expect(PhotosInSubjectAfterRenameCount).eql(PhotosInSubjectCount);
|
||||
}
|
||||
|
|
@ -111,8 +114,7 @@ test.meta("testID", "people-002").meta({ type: "short", mode: "public" })(
|
|||
const AndreaUID = await subject.getNthSubjectUid(0);
|
||||
await subject.openSubjectWithUid(AndreaUID);
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(5000);
|
||||
const PhotosInAndreaCount = await photo.getPhotoCount("all");
|
||||
const PhotosInAndreaCount = await photo.getPhotoCount("all", 13000);
|
||||
await photo.triggerHoverAction("nth", 1, "select");
|
||||
await contextmenu.triggerContextMenuAction("edit", "");
|
||||
await t
|
||||
|
|
@ -129,13 +131,11 @@ test.meta("testID", "people-002").meta({ type: "short", mode: "public" })(
|
|||
.click(photoedit.dialogClose);
|
||||
await contextmenu.clearSelection();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(5000);
|
||||
const PhotosInAndreaAfterRejectCount = await photo.getPhotoCount("all");
|
||||
const PhotosInAndreaAfterRejectCount = await photo.getPhotoCount("all", 13000);
|
||||
const Diff = PhotosInAndreaCount - PhotosInAndreaAfterRejectCount;
|
||||
await toolbar.search("person:nicole");
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(5000);
|
||||
const PhotosInNicoleCount = await photo.getPhotoCount("all");
|
||||
const PhotosInNicoleCount = await photo.getPhotoCount("all", 13000);
|
||||
|
||||
await t.expect(Diff).gte(PhotosInNicoleCount);
|
||||
}
|
||||
|
|
@ -200,8 +200,9 @@ test.meta("testID", "people-005").meta({ mode: "public" })("Common: Remove face"
|
|||
|
||||
await t.click(photoedit.dialogClose);
|
||||
await contextmenu.clearSelection();
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(5000);
|
||||
await notifies.waitForPhotosToLoad(5000, true);
|
||||
await photo.triggerHoverAction("uid", FirstPhotoUid, "select");
|
||||
await contextmenu.triggerContextMenuAction("edit", "");
|
||||
await t.click(photoedit.peopleTab);
|
||||
|
|
@ -234,17 +235,20 @@ test.meta("testID", "people-006").meta({ mode: "public" })("Common: Hide face",
|
|||
const FirstFaceID = await subject.getNthFaceUid(0);
|
||||
await subject.checkFaceVisibility(FirstFaceID, true);
|
||||
await subject.triggerHoverAction("id", FirstFaceID, "hidden");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(5000);
|
||||
await notifies.waitForPeopleToLoad(5000, true);
|
||||
await subject.checkFaceVisibility(FirstFaceID, false);
|
||||
await subject.triggerToolbarAction("show-hidden");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(6000);
|
||||
await notifies.waitForPeopleToLoad(6000, true);
|
||||
await subject.checkFaceVisibility(FirstFaceID, true);
|
||||
await subject.triggerHoverAction("id", FirstFaceID, "hidden");
|
||||
await subject.triggerToolbarAction("exclude-hidden");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(6000);
|
||||
await notifies.waitForPeopleToLoad(6000, true);
|
||||
await subject.checkFaceVisibility(FirstFaceID, true);
|
||||
});
|
||||
|
||||
|
|
@ -254,28 +258,33 @@ test.meta("testID", "people-007").meta({ mode: "public" })("Common: Hide person"
|
|||
const FirstPersonUid = await subject.getNthSubjectUid(0);
|
||||
await subject.checkSubjectVisibility("uid", FirstPersonUid, true);
|
||||
await subject.triggerHoverAction("uid", FirstPersonUid, "hidden");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(6000);
|
||||
await notifies.waitForPeopleToLoad(6000, true);
|
||||
await subject.checkSubjectVisibility("uid", FirstPersonUid, false);
|
||||
await subject.triggerToolbarAction("show-hidden");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(6000);
|
||||
await notifies.waitForPeopleToLoad(6000, true);
|
||||
await subject.checkSubjectVisibility("uid", FirstPersonUid, true);
|
||||
await subject.triggerHoverAction("uid", FirstPersonUid, "hidden");
|
||||
await subject.triggerToolbarAction("exclude-hidden");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.eval(() => location.reload());
|
||||
await t.wait(5000);
|
||||
await notifies.waitForPeopleToLoad(5000, true);
|
||||
await subject.checkSubjectVisibility("uid", FirstPersonUid, true);
|
||||
});
|
||||
|
||||
test.meta("testID", "people-008").meta({ mode: "public" })("Common: Go to person from face menu", async (t) => {
|
||||
await menu.openPage("people");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.click(subject.recognizedTab);
|
||||
await t.wait(2000);
|
||||
await notifies.waitForPeopleToLoad(2000, true);
|
||||
|
||||
const firstPersonUid = await subject.getNthSubjectUid(0);
|
||||
await notifies.closeAllEventPopups();
|
||||
await subject.openSubjectWithUid(firstPersonUid);
|
||||
await t.wait(2000);
|
||||
await notifies.waitForPhotosToLoad(2000, true);
|
||||
await photo.triggerHoverAction("nth", 0, "select");
|
||||
await contextmenu.triggerContextMenuAction("edit", "");
|
||||
await t.click(photoedit.peopleTab);
|
||||
|
|
@ -293,8 +302,9 @@ test.meta("testID", "people-008").meta({ mode: "public" })("Common: Go to person
|
|||
|
||||
test.meta("testID", "people-009").meta({ mode: "public" })("Common: Set person cover from face menu", async (t) => {
|
||||
await menu.openPage("people");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.click(subject.recognizedTab);
|
||||
await t.wait(3000);
|
||||
await notifies.waitForPeopleToLoad(3000, true);
|
||||
|
||||
const firstPersonUid = await subject.getNthSubjectUid(0);
|
||||
const personCard = Selector("div.result.is-subject[data-uid='" + firstPersonUid + "']");
|
||||
|
|
@ -305,9 +315,8 @@ test.meta("testID", "people-009").meta({ mode: "public" })("Common: Set person c
|
|||
.ok(`Could not get initial thumbnail for person ${firstPersonUid}`);
|
||||
|
||||
await subject.openSubjectWithUid(firstPersonUid);
|
||||
await t.wait(2000);
|
||||
|
||||
const photoCount = await photo.getPhotoCount("all");
|
||||
const photoCount = await photo.getPhotoCount("all", 9000);
|
||||
const photoIdx = photoCount > 1 ? 1 : 0;
|
||||
await photo.triggerHoverAction("nth", photoIdx, "select");
|
||||
await contextmenu.triggerContextMenuAction("edit", "");
|
||||
|
|
@ -315,15 +324,17 @@ test.meta("testID", "people-009").meta({ mode: "public" })("Common: Set person c
|
|||
|
||||
const faceName = await photoedit.inputName.nth(0).value;
|
||||
if (faceName && faceName !== "") {
|
||||
await notifies.closeAllEventPopups();
|
||||
await photoedit.setPersonCover(0);
|
||||
await t.wait(2000);
|
||||
await notifies.waitForPersonCoverUpdate(2000, true);
|
||||
|
||||
await t.click(photoedit.dialogClose);
|
||||
await contextmenu.clearSelection();
|
||||
|
||||
await menu.openPage("people");
|
||||
await notifies.closeAllEventPopups();
|
||||
await t.click(subject.recognizedTab);
|
||||
await t.wait(3000);
|
||||
await notifies.waitForPeopleToLoad(3000, true);
|
||||
|
||||
const updatedThumb = await personCard.find("div.preview img").getAttribute("src");
|
||||
await t
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import PhotoEdit from "../page-model/photo-edit";
|
|||
import Originals from "../page-model/originals";
|
||||
import Album from "../page-model/album";
|
||||
import Library from "../page-model/library";
|
||||
import Notifies from "../page-model/notifications";
|
||||
|
||||
fixture`Test photos upload and delete`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -22,6 +23,7 @@ const page = new Page();
|
|||
const photoedit = new PhotoEdit();
|
||||
const originals = new Originals();
|
||||
const library = new Library();
|
||||
const notifies = new Notifies();
|
||||
|
||||
test.meta("testID", "photos-upload-delete-001").meta({ type: "short", mode: "public" })(
|
||||
"Core: Upload + Delete jpg/json",
|
||||
|
|
@ -32,7 +34,7 @@ test.meta("testID", "photos-upload-delete-001").meta({ type: "short", mode: "pub
|
|||
await menu.openNav();
|
||||
const InitialOriginalsCount = await Selector("a.nav-originals span.nav-count-item", { timeout: 5000 }).innerText;
|
||||
await t.expect(fs.existsSync("../storage/acceptance/originals/2020/10")).notOk();
|
||||
await toolbar.search("digikam");
|
||||
await toolbar.search("digikam", false);
|
||||
const PhotoCount = await photo.getPhotoCount("all");
|
||||
|
||||
await t.expect(PhotoCount).eql(0);
|
||||
|
|
@ -42,8 +44,8 @@ test.meta("testID", "photos-upload-delete-001").meta({ type: "short", mode: "pub
|
|||
.setFilesToUpload(Selector(".input-upload"), [
|
||||
"../../upload-files/digikam.jpg",
|
||||
"../../upload-files/digikam.json",
|
||||
])
|
||||
.wait(15000);
|
||||
]);
|
||||
await notifies.waitForUpload();
|
||||
await toolbar.triggerToolbarAction("refresh");
|
||||
const PhotoCountAfterUpload = await photo.getPhotoCount("all");
|
||||
|
||||
|
|
@ -51,7 +53,7 @@ test.meta("testID", "photos-upload-delete-001").meta({ type: "short", mode: "pub
|
|||
|
||||
const UploadedPhoto = await photo.getNthPhotoUid("all", 0);
|
||||
await t.navigateTo("/library/index/files/2020/10");
|
||||
await t.wait(5000);
|
||||
await notifies.waitForFoldersToLoad(5000, true);
|
||||
const FileCount = await originals.getFileCount();
|
||||
|
||||
await t.expect(FileCount).eql(2);
|
||||
|
|
@ -106,13 +108,14 @@ test.meta("testID", "photos-upload-delete-002").meta({ mode: "public" })("Core:
|
|||
console.log("Skipped on mobile");
|
||||
} else {
|
||||
await t.expect(fs.existsSync("../storage/acceptance/originals/2020/06")).notOk();
|
||||
await toolbar.search("korn");
|
||||
await toolbar.search("korn", false);
|
||||
const PhotoCount = await photo.getPhotoCount("all");
|
||||
|
||||
await t.expect(PhotoCount).eql(0);
|
||||
|
||||
await toolbar.triggerToolbarAction("upload");
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/korn.mp4"]).wait(15000);
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/korn.mp4"]);
|
||||
await notifies.waitForUpload();
|
||||
await toolbar.triggerToolbarAction("refresh");
|
||||
const PhotoCountAfterUpload = await photo.getPhotoCount("all");
|
||||
|
||||
|
|
@ -120,7 +123,7 @@ test.meta("testID", "photos-upload-delete-002").meta({ mode: "public" })("Core:
|
|||
|
||||
const UploadedPhoto = await photo.getNthPhotoUid("all", 0);
|
||||
await t.navigateTo("/library/index/files/2020/06");
|
||||
await t.wait(5000);
|
||||
await notifies.waitForFoldersToLoad(5000, true);
|
||||
|
||||
const FileCount = await originals.getFileCount();
|
||||
|
||||
|
|
@ -180,10 +183,10 @@ test.meta("testID", "photos-upload-delete-003").meta({ mode: "public" })(
|
|||
await album.openAlbumWithUid(AlbumUid);
|
||||
const PhotoCount = await photo.getPhotoCount("all");
|
||||
await toolbar.triggerToolbarAction("upload");
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/ladybug.jpg"]).wait(15000);
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/ladybug.jpg"]);
|
||||
await notifies.waitForUpload();
|
||||
await toolbar.triggerToolbarAction("refresh");
|
||||
await t.wait(5000);
|
||||
const PhotoCountAfterUpload = await photo.getPhotoCount("all");
|
||||
const PhotoCountAfterUpload = await photo.getPhotoCount("all", 12000);
|
||||
|
||||
await t.expect(PhotoCountAfterUpload).eql(PhotoCount + 1);
|
||||
|
||||
|
|
@ -221,8 +224,8 @@ test.meta("testID", "photos-upload-delete-004").meta({ mode: "public" })(
|
|||
.click(Selector(".input-albums"))
|
||||
.typeText(Selector(".input-albums input"), "NewCreatedAlbum")
|
||||
.pressKey("enter")
|
||||
.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/digikam.jpg"])
|
||||
.wait(15000);
|
||||
.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/digikam.jpg"]);
|
||||
await notifies.waitForUpload();
|
||||
if (t.browser.platform === "mobile") {
|
||||
await t.eval(() => location.reload());
|
||||
} else {
|
||||
|
|
@ -252,8 +255,8 @@ test.meta("testID", "photos-upload-delete-004").meta({ mode: "public" })(
|
|||
await menu.openPage("albums");
|
||||
await toolbar.search("NewCreatedAlbum");
|
||||
await album.openNthAlbum(0);
|
||||
await photo.checkPhotoVisibility(UploadedPhotoUid, false);
|
||||
const PhotoCountAfterDelete = await photo.getPhotoCount("all");
|
||||
await photo.checkPhotoVisibility(UploadedPhotoUid, false);
|
||||
|
||||
await t.expect(PhotoCountAfterDelete).eql(0);
|
||||
|
||||
|
|
@ -273,7 +276,8 @@ test.meta("testID", "photos-upload-delete-005").meta({ type: "short", mode: "pub
|
|||
console.log("Skipped on mobile");
|
||||
} else {
|
||||
await toolbar.triggerToolbarAction("upload");
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/hentai_2.jpg"]).wait(15000);
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/hentai_2.jpg"]);
|
||||
await notifies.waitForUploadFailed();
|
||||
await t.click(Selector("button.action-close")).wait(8000);
|
||||
|
||||
await menu.openPage("library");
|
||||
|
|
@ -297,7 +301,8 @@ test.meta("testID", "photos-upload-delete-006").meta({ type: "short", mode: "pub
|
|||
await menu.openPage("browse");
|
||||
|
||||
await toolbar.triggerToolbarAction("upload");
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/foo.txt"]).wait(15000);
|
||||
await t.setFilesToUpload(Selector(".input-upload"), ["../../upload-files/foo.txt"]);
|
||||
await notifies.waitForUpload();
|
||||
await menu.openNav();
|
||||
const OriginalsCountAfterUpload = await Selector("a.nav-originals span.nav-count-item", {
|
||||
timeout: 10000,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import PhotoEdit from "../page-model/photo-edit";
|
|||
import Subject from "../page-model/subject";
|
||||
import Label from "../page-model/label";
|
||||
import Library from "../page-model/library";
|
||||
import Notifies from "../page-model/notifications";
|
||||
|
||||
fixture`Test Keyboard Shortcuts`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ const photoEdit = new PhotoEdit();
|
|||
const subject = new Subject();
|
||||
const label = new Label();
|
||||
const library = new Library();
|
||||
const notifies = new Notifies();
|
||||
|
||||
const triggerKeyPress = ClientFunction((key, code, keyCode, ctrlKey, shiftKey, targetSelector) => {
|
||||
const target = targetSelector ? document.querySelector(targetSelector) : document;
|
||||
|
|
@ -61,8 +63,9 @@ test.meta("testID", "shortcuts-001").meta({ type: "short", mode: "public" })(
|
|||
const initialScrollY = await getcurrentPosition();
|
||||
await t.expect(initialScrollY).gt(0, "Should have scrolled down before refresh");
|
||||
|
||||
await notifies.closeAllEventPopups();
|
||||
await triggerKeyPress("r", "KeyR", 82, true, false);
|
||||
await t.wait(2000); // Wait for page to reload
|
||||
await notifies.waitForPhotosToLoad(2000, true); // Wait for page to reload
|
||||
|
||||
const finalScrollY = await getcurrentPosition();
|
||||
await t.expect(finalScrollY).eql(initialScrollY, "Scroll position should be restored after refresh");
|
||||
|
|
@ -128,15 +131,11 @@ test.meta("testID", "shortcuts-003").meta({ type: "short", mode: "public" })(
|
|||
|
||||
await triggerKeyPress("a", "KeyA", 65, true, false);
|
||||
|
||||
await t.expect(Selector("div.p-notify--success").withText("Archived").visible).ok();
|
||||
|
||||
await t.wait(5000);
|
||||
await t.click(Selector("div.p-notify--success").withText("Archived"));
|
||||
|
||||
await triggerKeyPress("a", "KeyA", 65, true, false);
|
||||
|
||||
await t.expect(Selector("div.p-notify--success").withText("Restored").visible).ok();
|
||||
|
||||
await t.wait(5000);
|
||||
await t.click(Selector("div.p-notify--success").withText("Restored"));
|
||||
|
||||
await triggerKeyPress("d", "KeyD", 68, true, false);
|
||||
await t.expect(Selector("div.p-notify--success").withText("Downloading").visible).ok();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import PhotoViewer from "../page-model/photoviewer";
|
|||
import Page from "../page-model/page";
|
||||
import PhotoEdit from "../page-model/photo-edit";
|
||||
import Library from "../page-model/library";
|
||||
import Notifies from "../page-model/notifications";
|
||||
|
||||
fixture`Test stacks`.page`${testcafeconfig.url}`;
|
||||
|
||||
|
|
@ -17,6 +18,7 @@ const photoviewer = new PhotoViewer();
|
|||
const page = new Page();
|
||||
const photoedit = new PhotoEdit();
|
||||
const library = new Library();
|
||||
const notifies = new Notifies();
|
||||
|
||||
test.meta("testID", "stacks-001").meta({ type: "short", mode: "public" })(
|
||||
"Common: View all files of a stack",
|
||||
|
|
@ -57,9 +59,9 @@ test.meta("testID", "stacks-002").meta({ type: "short", mode: "public" })("Commo
|
|||
});
|
||||
|
||||
test.meta("testID", "stacks-003").meta({ type: "short", mode: "public" })("Common: Ungroup files", async (t) => {
|
||||
await toolbar.search("group");
|
||||
await t.click(toolbar.cardsViewAction);
|
||||
await toolbar.search("group", false);
|
||||
const PhotoCount = await photo.getPhotoCount("all");
|
||||
await t.click(toolbar.cardsViewAction);
|
||||
const SequentialPhotoUid = await photo.getNthPhotoUid("all", 0);
|
||||
|
||||
await t.expect(PhotoCount).eql(1);
|
||||
|
|
@ -72,9 +74,9 @@ test.meta("testID", "stacks-003").meta({ type: "short", mode: "public" })("Commo
|
|||
.click(photoedit.filesTab)
|
||||
.click(photoedit.toggleExpandFile.nth(0))
|
||||
.click(photoedit.toggleExpandFile.nth(1))
|
||||
.click(photoedit.unstackFile)
|
||||
.wait(12000)
|
||||
.click(photoedit.dialogClose);
|
||||
.click(photoedit.unstackFile);
|
||||
await notifies.waitForUnstack();
|
||||
await t.click(photoedit.dialogClose);
|
||||
await menu.openPage("browse");
|
||||
await toolbar.search("group");
|
||||
if (t.browser.platform === "mobile") {
|
||||
|
|
@ -94,12 +96,12 @@ test.meta("testID", "stacks-004").meta({ mode: "public" })("Common: Delete non p
|
|||
.click(library.importTab)
|
||||
.click(library.openImportFolderSelect)
|
||||
.click(page.selectOption.withText("/pizza"))
|
||||
.click(library.import)
|
||||
.wait(10000);
|
||||
.click(library.import);
|
||||
await notifies.waitForImport();
|
||||
await menu.openPage("browse");
|
||||
await toolbar.search("pizza");
|
||||
await t.click(toolbar.cardsViewAction);
|
||||
await toolbar.search("pizza", false);
|
||||
const PhotoCount = await photo.getPhotoCount("all");
|
||||
await t.click(toolbar.cardsViewAction);
|
||||
const PhotoUid = await photo.getNthPhotoUid("all", 0);
|
||||
|
||||
await t.expect(PhotoCount).eql(1);
|
||||
|
|
@ -113,8 +115,8 @@ test.meta("testID", "stacks-004").meta({ mode: "public" })("Common: Delete non p
|
|||
await t
|
||||
.click(photoedit.toggleExpandFile.nth(1))
|
||||
.click(Selector(photoedit.deleteFile))
|
||||
.click(Selector(".action-confirm"))
|
||||
.wait(10000);
|
||||
.click(Selector(".action-confirm"));
|
||||
await notifies.waitForFileDeleted();
|
||||
const FileCountAfterDeletion = await photoedit.getFileCount();
|
||||
|
||||
await t.expect(FileCountAfterDeletion).eql(1);
|
||||
|
|
|
|||
|
|
@ -1,18 +1,28 @@
|
|||
import { Selector, t } from "testcafe";
|
||||
|
||||
const showLogs = process.env.SHOW_LOGS == "true";
|
||||
|
||||
export default class Page {
|
||||
constructor() {
|
||||
this.navDrawer = Selector(".v-navigation-drawer");
|
||||
this.navActive = Selector(".v-navigation-drawer--active");
|
||||
this.navInRail = Selector(".v-navigation-drawer--rail");
|
||||
this.expandButton = Selector("div.nav-expand i");
|
||||
this.expandButtonContainer = Selector("div.nav-expand");
|
||||
}
|
||||
|
||||
async openNav() {
|
||||
if (await this.expandButton.visible) {
|
||||
await t.click(this.expandButton);
|
||||
} else if (await this.expandButtonContainer.visible) {
|
||||
await t.click(this.expandButton);
|
||||
showLogs && console.time("openNav")
|
||||
if (await this.navActive.visible) { // Make sure that the nav has been rendered
|
||||
if (await this.navInRail.exists) { // fail fast looking for a minimized nav
|
||||
if (await this.expandButton.exists) {
|
||||
await t.click(this.expandButton);
|
||||
} else if (await this.expandButtonContainer.exists) {
|
||||
await t.click(this.expandButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
showLogs && console.timeEnd("openNav")
|
||||
}
|
||||
|
||||
async openPage(page) {
|
||||
|
|
|
|||
140
frontend/tests/acceptance/page-model/notifications.js
Normal file
140
frontend/tests/acceptance/page-model/notifications.js
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
import { Selector, t } from "testcafe";
|
||||
|
||||
const showLogs = process.env.SHOW_LOGS == "true";
|
||||
const waitAfterClick = 350 // Please note that all t.click have to wait to allow the clicked item time to go away (300ms fade out).
|
||||
|
||||
export default class Page {
|
||||
constructor() {
|
||||
this.notifyClose250 = Selector(".p-notify__close", {timeout: 250})
|
||||
}
|
||||
|
||||
logMessage(message) {
|
||||
var now = new Date();
|
||||
console.log(now.toISOString() + " " + message);
|
||||
}
|
||||
|
||||
// closeAllEventPopups will close any event popups that are open, ignoring any click issues.
|
||||
async closeAllEventPopups() {
|
||||
showLogs && console.time("closeAllEventPopups");
|
||||
showLogs && this.logMessage("Before While in closeAllEventPopups");
|
||||
while(await this.notifyClose250.visible) {
|
||||
try {
|
||||
showLogs && this.logMessage("Before Click in closeAllEventPopups");
|
||||
await t.click(this.notifyClose250).wait(waitAfterClick);
|
||||
showLogs && this.logMessage("After Click in closeAllEventPopups");
|
||||
} catch {
|
||||
showLogs && this.logMessage("After Click In Catch in closeAllEventPopups");
|
||||
showLogs && console.trace("notify close missed in closeAllEventPopups")
|
||||
}
|
||||
}
|
||||
showLogs && console.timeEnd("closeAllEventPopups");
|
||||
}
|
||||
|
||||
// waitForSpecficEvent will wait for the event to show up, for delay amount of time (after closing any event messages that do not match).
|
||||
async waitForSpecficEvent(event, delay = 7000, close = true) {
|
||||
showLogs && this.logMessage("Before While in waitForSpecficEvent");
|
||||
while(await this.notifyClose250.visible) {
|
||||
if (await Selector("div.p-notify__text", {timeout: 50}).withText(event).visible) {
|
||||
try {
|
||||
if (close) {
|
||||
showLogs && this.logMessage("Before Click in waitForSpecficEvent");
|
||||
await t.click(this.notifyClose250).wait(waitAfterClick);
|
||||
showLogs && this.logMessage("After Click in waitForSpecficEvent");
|
||||
}
|
||||
} catch {
|
||||
// ignore the error as the item may not show up
|
||||
showLogs && this.logMessage("After Click In Catch in waitForSpecficEvent");
|
||||
console.trace("notify close missed in waitForSpecficEvent " + event)
|
||||
} finally {
|
||||
return
|
||||
}
|
||||
}
|
||||
try {
|
||||
showLogs && this.logMessage("Before Click in waitForSpecficEvent");
|
||||
await t.click(this.notifyClose250).wait(waitAfterClick);
|
||||
showLogs && this.logMessage("After Click in waitForSpecficEvent");
|
||||
} catch {
|
||||
showLogs && this.logMessage("After Click In Catch in waitForSpecficEvent");
|
||||
showLogs && console.trace("notify close missed in waitForSpecficEvent Pre")
|
||||
}
|
||||
}
|
||||
showLogs && this.logMessage("Before Visible in waitForSpecficEvent");
|
||||
if ((await Selector("div.p-notify__text", {timeout: delay}).withText(event).visible) && close){
|
||||
try {
|
||||
showLogs && this.logMessage("Before Click in waitForSpecficEvent");
|
||||
await t.click(this.notifyClose250).wait(waitAfterClick);
|
||||
showLogs && this.logMessage("After Click in waitForSpecficEvent");
|
||||
} catch {
|
||||
// ignore the error as the item may not show up
|
||||
showLogs && this.logMessage("After Click In Catch in waitForSpecficEvent");
|
||||
showLogs && console.trace("notify close missed in waitForSpecficEvent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async waitForFileDeleted(delay = 10000, close = true) {
|
||||
showLogs && console.time("waitForFileDeleted")
|
||||
await this.waitForSpecficEvent("File deleted", delay, close);
|
||||
showLogs && console.timeEnd("waitForFileDeleted")
|
||||
}
|
||||
|
||||
async waitForFoldersToLoad(delay, close) {
|
||||
showLogs && console.time("waitForFoldersToLoad")
|
||||
await this.waitForSpecficEvent(/[fF]older/, delay, close);
|
||||
showLogs && console.timeEnd("waitForFoldersToLoad")
|
||||
}
|
||||
|
||||
async waitForImport(delay = 10000, close = true) {
|
||||
showLogs && console.time("waitForImport")
|
||||
await this.waitForSpecficEvent("Import completed in", delay, close);
|
||||
showLogs && console.timeEnd("waitForImport")
|
||||
}
|
||||
|
||||
async waitForIndexing(delay = 10000, close = true) {
|
||||
showLogs && console.time("waitForIndexing")
|
||||
await this.waitForSpecficEvent("Indexing completed in", delay, close);
|
||||
showLogs && console.timeEnd("waitForIndexing")
|
||||
}
|
||||
|
||||
async waitForPeopleToLoad(delay, close = true) {
|
||||
showLogs && console.time("waitForPeopleToLoad")
|
||||
await this.waitForSpecficEvent(/(people|person) (found|loaded)/, delay, close);
|
||||
showLogs && console.timeEnd("waitForPeopleToLoad")
|
||||
}
|
||||
|
||||
async waitForPersonCoverUpdate(delay, close = true) {
|
||||
showLogs && console.time("waitForPersonCoverUpdate")
|
||||
await this.waitForSpecficEvent("Person cover updated", delay, close);
|
||||
showLogs && console.timeEnd("waitForPersonCoverUpdate")
|
||||
}
|
||||
|
||||
async waitForPhotosToLoad(delay, close = true){
|
||||
showLogs && console.time("waitForPhotosToLoad")
|
||||
await this.waitForSpecficEvent(/(picture|pictures) found/, delay, close);
|
||||
showLogs && console.timeEnd("waitForPhotosToLoad")
|
||||
}
|
||||
|
||||
async waitForSearchToFinish(delay, close = true){
|
||||
showLogs && console.time("waitForSearchToFinish")
|
||||
await this.waitForSpecficEvent(/(found|contain|empty)/, delay, close);
|
||||
showLogs && console.timeEnd("waitForSearchToFinish")
|
||||
}
|
||||
|
||||
async waitForUnstack(delay = 12000, close = true) {
|
||||
showLogs && console.time("waitForUnstack")
|
||||
await this.waitForSpecficEvent("File removed from stack", delay, close);
|
||||
showLogs && console.timeEnd("waitForUnstack")
|
||||
}
|
||||
|
||||
async waitForUpload(delay = 15000, close = true) {
|
||||
showLogs && console.time("waitForUpload")
|
||||
await this.waitForSpecficEvent("Upload has been processed", delay, close);
|
||||
showLogs && console.timeEnd("waitForUpload")
|
||||
}
|
||||
|
||||
async waitForUploadFailed(delay = 15000, close = true) {
|
||||
showLogs && console.time("waitForUploadFailed")
|
||||
await this.waitForSpecficEvent("Upload failed", delay, close);
|
||||
showLogs && console.timeEnd("waitForUploadFailed")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { Selector, t } from "testcafe";
|
||||
import Toolbar from "./toolbar";
|
||||
import Notifies from "../page-model/notifications";
|
||||
|
||||
const toolbar = new Toolbar();
|
||||
const notifies = new Notifies();
|
||||
|
||||
export default class Page {
|
||||
constructor() {}
|
||||
|
|
@ -18,8 +18,8 @@ export default class Page {
|
|||
}
|
||||
}
|
||||
|
||||
async getPhotoCount(type) {
|
||||
await t.wait(7000);
|
||||
async getPhotoCount(type, delay = 7000) {
|
||||
await notifies.waitForPhotosToLoad(delay, true)
|
||||
if (type === "all") {
|
||||
const PhotoCount = await Selector("div.is-photo", { timeout: 2000 }).count;
|
||||
return PhotoCount;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { Selector, t } from "testcafe";
|
||||
import Notifies from "../page-model/notifications";
|
||||
const notifies = new Notifies();
|
||||
|
||||
export default class Page {
|
||||
constructor() {
|
||||
|
|
@ -137,8 +139,13 @@ export default class Page {
|
|||
}
|
||||
}
|
||||
|
||||
async search(term) {
|
||||
await t.click(this.search1).typeText(this.search1, term, { replace: true }).pressKey("enter").wait(7000);
|
||||
async search(term, wait = true) {
|
||||
await notifies.closeAllEventPopups();
|
||||
|
||||
await t.click(this.search1).typeText(this.search1, term, { replace: true }).pressKey("enter");
|
||||
if (wait) {
|
||||
await notifies.waitForSearchToFinish(7000);
|
||||
}
|
||||
}
|
||||
|
||||
async setFilter(filter, option) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue