Art uploads art as NZAP, admin approves, art displays on user page Renders/art/new /u/:identifier /u/:identifier/art /upload/admin
New art page User art page Image validation page User art page Arrange
Grant user N-ZAP roles “ARTIST”
await factories.UserFactory .grant (NZAP_TEST_ID , { roles: ["ARTIST" ] });New art page Act
Open the new art page
await newArt.goto ();Select image TEST_IMAGE_PATH
await newArt.selectImage (TEST_IMAGE_PATH );Assert
preview is visible
await expect (newArt.locators.preview).toBeVisible ();Act
Save → userArt
const userArt = await newArt.save ();Assert
the page URL is /\/u\/.*\/art/
await expect (page).toHaveURL (/\/u\/.*\/art/);User art page Assert
pending approval text is visible
await expect (userArt.locators.pendingApprovalText).toBeVisible ();Image validation page Act
Open the image validation page
await imageValidation.goto ();Assert
first images is visible
await expect (imageValidation.locators.images.first ()).toBeVisible ();Act
Approve all
await imageValidation.approveAll ();Assert
all validated text is visible
await expect (imageValidation.locators.allValidatedText).toBeVisible ();User art page Act
Open the user art page N-ZAP
await userArt.goto (NZAP_TEST_ID );Image 0 → artImage
const artImage = userArt.image (0 );Assert
artImage is visible
await expect (artImage).toBeVisible ();Act
Bounding box → box
const box = await artImage.boundingBox ();Assert
box is not null
expect (box).not.toBeNull ();box!.width is more than 0
expect (box!.width).toBeGreaterThan (0 );box!.height is more than 0
expect (box!.height).toBeGreaterThan (0 );Source test ("uploads art as NZAP, admin approves, art displays on user page" , async ({
page,
factories,
}) => {
await factories.UserFactory .grant (NZAP_TEST_ID , { roles: ["ARTIST" ] });
await impersonate (page, NZAP_TEST_ID );
const newArt = new NewArtPage (page);
await newArt.goto ();
await newArt.selectImage (TEST_IMAGE_PATH );
await expect (newArt.locators.preview).toBeVisible ();
const userArt = await newArt.save ();
await expect (page).toHaveURL (/\/u\/.*\/art/);
await expect (userArt.locators.pendingApprovalText).toBeVisible ();
await impersonate (page);
const imageValidation = new ImageValidationPage (page);
await imageValidation.goto ();
await expect (imageValidation.locators.images.first ()).toBeVisible ();
await imageValidation.approveAll ();
await expect (imageValidation.locators.allValidatedText).toBeVisible ();
await userArt.goto (NZAP_TEST_ID );
const artImage = userArt.image (0 );
await expect (artImage).toBeVisible ();
const box = await artImage.boundingBox ();
expect (box).not.toBeNull ();
expect (box!.width).toBeGreaterThan (0 );
expect (box!.height).toBeGreaterThan (0 );
})edits own art, unlinks from art made of them and deletes own art Renders/art/new /u/:identifier /u/:identifier/art
User art page New art page User art page Arrange
Grant user N-ZAP roles “ARTIST”
await factories.UserFactory .grant (NZAP_TEST_ID , { roles: ["ARTIST" ] });Create art author N-ZAP → art
const art = await factories.ArtFactory .create ({ authorId: NZAP_TEST_ID });Create art author Sendou linked users N-ZAP
await factories.ArtFactory .create ({
authorId: ADMIN_ID ,
linkedUsers: [NZAP_TEST_ID ],
});User art page Act
Open the user art page N-ZAP
await userArt.goto (NZAP_TEST_ID );Click edit link art.id
await userArt.editLink (art.id).click ();New art page Assert
the already uploaded image is shown but can't be swapped only rendering is asserted as the factory made art has no image file
existing image is in the page
await expect (newArt.locators.existingImage).toBeAttached ();file input count is 0
await expect (newArt.locators.fileInput).toHaveCount (0 );Act
Fill description with “Squid drawing”
await newArt.form.fill ("description" , "Squid drawing" );Save
await newArt.save ();Assert
the page URL is /\/u\/.*\/art/
await expect (page).toHaveURL (/\/u\/.*\/art/);Act
the saved description is loaded back into the form for editing
Open the new art page art.id
await newArt.goto (art.id);Assert
description input has value “Squid drawing”
await expect (newArt.locators.descriptionInput).toHaveValue ("Squid drawing" );User art page Act
both their own art and the art they are tagged in show on their page
Open the user art page N-ZAP
await userArt.goto (NZAP_TEST_ID );Assert
images count is 2
await expect (userArt.locators.images).toHaveCount (2 );Act
Unlink from art
await userArt.unlinkFromArt ();Assert
images count is 1
await expect (userArt.locators.images).toHaveCount (1 );unlink button is not visible
await isNotVisible (userArt.locators.unlinkButton);Act
Delete art
await userArt.deleteArt ();Assert
images count is 0
await expect (userArt.locators.images).toHaveCount (0 );Source test ("edits own art, unlinks from art made of them and deletes own art" , async ({
page,
factories,
}) => {
await factories.UserFactory .grant (NZAP_TEST_ID , { roles: ["ARTIST" ] });
const art = await factories.ArtFactory .create ({ authorId: NZAP_TEST_ID });
await factories.ArtFactory .create ({
authorId: ADMIN_ID ,
linkedUsers: [NZAP_TEST_ID ],
});
await impersonate (page, NZAP_TEST_ID );
const userArt = new UserArtPage (page);
await userArt.goto (NZAP_TEST_ID );
await userArt.editLink (art.id).click ();
const newArt = new NewArtPage (page);
// the already uploaded image is shown but can't be swapped
// only rendering is asserted as the factory made art has no image file
await expect (newArt.locators.existingImage).toBeAttached ();
await expect (newArt.locators.fileInput).toHaveCount (0 );
await newArt.form.fill ("description" , "Squid drawing" );
await newArt.save ();
await expect (page).toHaveURL (/\/u\/.*\/art/);
// the saved description is loaded back into the form for editing
await newArt.goto (art.id);
await expect (newArt.locators.descriptionInput).toHaveValue ("Squid drawing" );
// both their own art and the art they are tagged in show on their page
await userArt.goto (NZAP_TEST_ID );
await expect (userArt.locators.images).toHaveCount (2 );
await userArt.unlinkFromArt ();
await expect (userArt.locators.images).toHaveCount (1 );
await isNotVisible (userArt.locators.unlinkButton);
await userArt.deleteArt ();
await expect (userArt.locators.images).toHaveCount (0 );
})NewArtPage.gotoe2e/pages/art/new-art-page.ts:27
async goto (artId?: Tables ["Art" ]["id" ]) {
await navigate ({ page: this .page, url: newArtPage (artId) });
}NewArtPage.selectImagee2e/pages/art/new-art-page.ts:31
No JSDoc
async selectImage (filePath: string ) {
await this .locators.fileInput.setInputFiles (filePath);
}NewArtPage.locators.previewe2e/pages/art/new-art-page.ts:20
No JSDoc
this .page.locator ("form img" )NewArtPage.savee2e/pages/art/new-art-page.ts:36
async save () {
// the upload alone can outlast an assertion's timeout under load
await waitForPOSTResponse (this .page, () => this .form.submit ());
return new UserArtPage (this .page);
}UserArtPage.locators.pendingApprovalTexte2e/pages/art/user-art-page.ts:15
No JSDoc
this .page.getByText (/pending moderator approval/i)ImageValidationPage.gotoe2e/pages/img-upload/image-validation-page.ts:22
No JSDoc
async goto () {
await navigate ({ page: this .page, url: IMAGE_VALIDATION_PAGE });
}ImageValidationPage.locators.imagese2e/pages/img-upload/image-validation-page.ts:14
No JSDoc
this .page.locator ("main img" )ImageValidationPage.approveAlle2e/pages/img-upload/image-validation-page.ts:26
No JSDoc
async approveAll () {
await this .locators.approveAllButton.click ();
}ImageValidationPage.locators.allValidatedTexte2e/pages/img-upload/image-validation-page.ts:18
No JSDoc
this .page.getByText ("All validated!" )UserArtPage.gotoe2e/pages/art/user-art-page.ts:21
No JSDoc
async goto (userId: number ) {
await navigate ({ page: this .page, url: userArtPage ({ id: userId }) });
}UserArtPage.imagee2e/pages/art/user-art-page.ts:25
No JSDoc
image (nth: number ) {
return this .locators.images.nth (nth);
}NewArtPagee2e/pages/art/new-art-page.ts:10
UserArtPagee2e/pages/art/user-art-page.ts:7
ImageValidationPagee2e/pages/img-upload/image-validation-page.ts:7
UserArtPage.editLinke2e/pages/art/user-art-page.ts:29
No JSDoc
editLink (artId: Tables ["Art" ]["id" ]) {
return this .page.locator (`a[href="${newArtPage(artId)}"]` );
}NewArtPage.locators.existingImagee2e/pages/art/new-art-page.ts:21
No JSDoc
this .page.locator ('form img[src*="-small."]' )NewArtPage.locators.fileInpute2e/pages/art/new-art-page.ts:19
No JSDoc
this .page.locator ('input[type="file"]' )NewArtPage.locators.descriptionInpute2e/pages/art/new-art-page.ts:22
No JSDoc
this .page.getByLabel (this .form.getLabel ("description" ))UserArtPage.locators.imagese2e/pages/art/user-art-page.ts:14
No JSDoc
this .page.getByTestId ("art-image" )UserArtPage.unlinkFromArte2e/pages/art/user-art-page.ts:40
async unlinkFromArt () {
await this .locators.unlinkButton.click ();
await modalClickConfirmButton (this .page);
}UserArtPage.locators.unlinkButtone2e/pages/art/user-art-page.ts:17
No JSDoc
this .page.getByTestId ("unlink-art-button" )isNotVisiblee2e/helpers/playwright.ts:745
No JSDoc
export function isNotVisible (locator: Locator ) {
return expect (locator).toHaveCount (0 );
}UserArtPage.deleteArte2e/pages/art/user-art-page.ts:34
async deleteArt () {
await this .locators.deleteButton.click ();
await modalClickConfirmButton (this .page);
}