Added csv validation, members export Playwright test

ref https://github.com/TryGhost/Team/issues/2371

- updated Member exports with csv validation
- added member fixtures to be loaded into Ghost to ensure filtering
  works correctly when downloading / exporting members csv.
This commit is contained in:
Ronald Langeveld 2022-12-08 16:30:32 +07:00
parent c1fc0d8888
commit 3e62764a64

View File

@ -1,5 +1,6 @@
const {expect, test} = require('@playwright/test');
const {createMember} = require('../utils/e2e-browser-utils');
const fs = require('fs');
test.describe('Admin', () => {
test.describe('Members', () => {
@ -104,13 +105,33 @@ test.describe('Admin', () => {
email: 'test@member3.com',
note: 'This is a test member',
label: 'Test Label'
},
{
name: 'Sashi',
email: 'test@member4.com',
note: 'This is a test member',
label: 'dog'
},
{
name: 'Mia',
email: 'test@member5.com',
note: 'This is a test member',
label: 'dog'
},
{
name: 'Minki',
email: 'test@member6.com',
note: 'This is a test member',
label: 'dog'
}
];
test('All members can be exported', async ({page}) => {
// adds 6 members, 3 with the same label
for (let member of membersFixture) {
await createMember(page, member);
}
await page.goto('/ghost');
await page.locator('.gh-nav a[href="#/members/"]').click();
await page.waitForSelector('button[data-test-button="members-actions"]');
await page.locator('button[data-test-button="members-actions"]').click();
@ -121,6 +142,24 @@ test.describe('Admin', () => {
]);
const filename = await download.suggestedFilename();
expect(filename).toContain('.csv');
const csv = await download.path();
let csvContents = await fs.readFileSync(csv).toString();
expect(csvContents).toMatch(/id,email,name,note,subscribed_to_emails,complimentary_plan,stripe_customer_id,created_at,deleted_at,labels,tiers/);
membersFixture.forEach((member) => {
expect(csvContents).toMatch(member.name);
expect(csvContents).toMatch(member.email);
expect(csvContents).toMatch(member.note);
expect(csvContents).toMatch(member.label);
});
// expect(csvContents).toMatch('Test Label'); we deleted the label in a previous test so it's not in this the export
const countIds = csvContents.match(/[a-z0-9]{24}/gm).length;
expect(countIds).toEqual(6);
const countTimestamps = csvContents.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/gm).length;
expect(countTimestamps).toEqual(6);
const countRows = csvContents.match(/(?:"(?:[^"]|"")*"|[^,\n]*)(?:,(?:"(?:[^"]|"")*"|[^,\n]*))*\n/g).length;
expect(countRows).toEqual(6);
const csvRegex = /^[^",]+((?<=[,\n])|(?=[,\n]))|[^",]+/gm;
expect(csvContents).toMatch(csvRegex);
});
test('A filtered list of members can be exported', async ({page}) => {
@ -131,7 +170,10 @@ test.describe('Admin', () => {
await page.waitForSelector('div[data-test-button="members-filter-actions"]');
await page.locator('div[data-test-button="members-filter-actions"]').click();
await page.locator('select[data-test-select="members-filter"]').click();
await page.locator('select[data-test-select="members-filter"]').selectOption('subscribed');
await page.locator('select[data-test-select="members-filter"]').selectOption('label');
await page.locator('div[data-test-members-filter="0"] > div > div').click();
await page.locator('span[data-test-label-filter="dog"]').click();
await page.keyboard.press('Tab');
await page.locator('button[data-test-button="members-apply-filter"]').click();
await page.locator('button[data-test-button="members-actions"]').click();
const exportButton = await page.locator('button[data-test-button="export-members"] > span').innerText();
@ -143,6 +185,27 @@ test.describe('Admin', () => {
]);
const filename = await download.suggestedFilename();
expect(filename).toContain('.csv');
const csv = await download.path();
let csvContents = await fs.readFileSync(csv).toString();
expect(csvContents).toMatch(/id,email,name,note,subscribed_to_emails,complimentary_plan,stripe_customer_id,created_at,deleted_at,labels,tiers/);
// filter memberFixtures to only include members with the label 'dog'
const filteredMembersFixture = membersFixture.filter((member) => {
return member.label === 'dog';
});
filteredMembersFixture.forEach((member) => {
expect(csvContents).toMatch(member.name);
expect(csvContents).toMatch(member.email);
expect(csvContents).toMatch(member.note);
expect(csvContents).toMatch('dog');
});
const countIds = csvContents.match(/[a-z0-9]{24}/gm).length;
expect(countIds).toEqual(3);
const countTimestamps = csvContents.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/gm).length;
expect(countTimestamps).toEqual(3);
const countRows = csvContents.match(/(?:"(?:[^"]|"")*"|[^,\n]*)(?:,(?:"(?:[^"]|"")*"|[^,\n]*))*\n/g).length;
expect(countRows).toEqual(3);
const csvRegex = /^[^",]+((?<=[,\n])|(?=[,\n]))|[^",]+/gm;
expect(csvContents).toMatch(csvRegex);
});
});
});