mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
* e2e: exercise the FileBrowser footer buttons against real files Sixteen Cypress tests covering Rename, Move, Delete (including the tagged-file force-delete flow), Ignore/Unignore, Upload, and scoped Refresh, with no API mocking: fb:* tasks seed a cypress-fb/ sandbox inside the media directory, the UI mutates it through the real API, and assertions check the disk as well as the table. Skipped in CI, which runs only the React dev server. Background jobs (move, refresh) only queue work and worker_status reads idle while jobs wait, so cy.refreshFiles / cy.waitForEvent poll the events feed for completion events newer than the server's clock, and fail loudly when one never arrives. Every suite cleans up unconditionally: sandbox files, DB rows via a final refresh, test tags and their tags/ directories, and any leaked ignored-directory config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * e2e: act on review — drain stragglers, teardown that cannot be skipped Events carry no job id, so waitForEvent cannot prove WHICH job finished. The rename tests now drain the parent-directory refresh their rename queues before ending, so the next test's refresh wait cannot be satisfied by a straggler while the DB still reflects the old tree; move waits match the destination in the completion message. Teardown must always reach the disk wipe: a failed command aborts the rest of its hook, so the tag cleanup and the DB-purge refresh are now best-effort (failOnStatusCode: false, no assertions), and the unignore runs after every test instead of once per spec. History and forward-looking product notes trimmed from comments. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
79 lines
3.4 KiB
JavaScript
79 lines
3.4 KiB
JavaScript
/*
|
|
* Shared helpers for the FileBrowser e2e specs (cypress/e2e/files/).
|
|
*
|
|
* These specs run against the live stack with real files: the fb:* tasks
|
|
* (cypress.config.js) seed a `cypress-fb/` sandbox inside the media directory,
|
|
* and cy.refreshFiles (support/commands.js) keeps the DB in sync with it.
|
|
*/
|
|
|
|
export const SANDBOX = 'cypress-fb';
|
|
|
|
export const footerButton = (label) => cy.get('.sticky-footer').contains('button', label);
|
|
export const row = (name) => cy.contains('tr', name);
|
|
export const selectRow = (name) => row(name).find('input[type="checkbox"]').check({force: true});
|
|
export const deselectRow = (name) => row(name).find('input[type="checkbox"]').uncheck({force: true});
|
|
export const dialog = () => cy.get('[role="dialog"]');
|
|
|
|
// WROL mode silently disables most footer buttons; fail loudly instead of reporting
|
|
// false failures. Call once from a spec's before().
|
|
export const assertWROLModeOff = () => {
|
|
cy.request('/api/settings').its('body.wrol_mode').then((wrolMode) => {
|
|
expect(wrolMode, 'WROL mode must be OFF for FileBrowser e2e tests (Admin > Settings)')
|
|
.to.be.false;
|
|
});
|
|
};
|
|
|
|
/*
|
|
* Seed the sandbox, sync the DB, open /files, and open the sandbox folder.
|
|
* `firstRow` should be a seeded name that proves the folder's children rendered.
|
|
*/
|
|
export const setupFileBrowser = (seedFiles, firstRow) => {
|
|
cy.task('fb:reset', {files: seedFiles});
|
|
cy.refreshFiles([SANDBOX]);
|
|
// The footer shows labeled buttons only when it is at least 1050px wide.
|
|
cy.viewport(1280, 800);
|
|
cy.visit('/files');
|
|
// A fresh page load replays recent events as toasts (each test run adds more), and
|
|
// they stack over the sticky footer, making cy.click() refuse the buttons. These
|
|
// specs assert on the disk and the table, not toasts, so hide the notification layer.
|
|
cy.document().then((doc) => {
|
|
const style = doc.createElement('style');
|
|
style.textContent = '.mantine-Notifications-root { display: none !important; }';
|
|
doc.head.appendChild(style);
|
|
});
|
|
cy.contains('.file-path', SANDBOX).click();
|
|
row(firstRow).should('be.visible');
|
|
};
|
|
|
|
// Empty the sandbox on disk, let a refresh purge its rows from the DB, then remove the
|
|
// empty directory itself so nothing stale survives into the next run. Call from after().
|
|
//
|
|
// The refresh is best-effort and never fails: a failed command aborts the rest of its hook,
|
|
// and the disk wipe below must always run. The next run's setup refresh repairs the DB
|
|
// even when this purge is missed.
|
|
export const teardownFileBrowser = () => {
|
|
cy.task('fb:reset', {files: {}});
|
|
cy.serverNow().then((since) => {
|
|
cy.request({
|
|
method: 'POST',
|
|
url: '/api/files/refresh',
|
|
body: {paths: [SANDBOX]},
|
|
failOnStatusCode: false,
|
|
});
|
|
const deadline = Date.now() + 30000;
|
|
const poll = () => {
|
|
cy.request({
|
|
url: `/api/events/feed?after=${encodeURIComponent(since)}`,
|
|
failOnStatusCode: false,
|
|
}).then(({body}) => {
|
|
const done = ((body && body.events) || []).some((e) =>
|
|
e.event === 'directory_refresh' && e.message === `Refreshed: ${SANDBOX}`);
|
|
if (done || Date.now() > deadline) return;
|
|
cy.wait(1000);
|
|
poll();
|
|
});
|
|
};
|
|
poll();
|
|
});
|
|
cy.task('fb:cleanup');
|
|
};
|