Codeinwp / Codeinwp/feedzy-rss-feeds
[DEV] Flaky interface for Feed Edit page
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 121
- Forks
- 27
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 11
Description
Problem
The interface for Feed Edit is pretty chaotic for the automated browser. Some click events might not trigger all interactions, thus making the test fail.
In both Playwright and Cypress, when using fields made with Tagify, the values will not be saved in the input. Thus, we need a separate function to inject the value into the input.
Example of E2E that we should have for it
test( 'changing General Feed Settings', async({ editor, page }) => {
const importName = 'Test Title: changing General Feed Settings';
await page.goto('/wp-admin/post-new.php?post_type=feedzy_imports');
await tryCloseTourModal( page );
await page.getByPlaceholder('Add a name for your import').fill(importName);
await addFeeds( page, [FEED_URL] );
await page.getByRole('button', { name: 'Step 4 General feed settings' }).click({ force: true });
// Change duplicated items setting.
const duplicatedItemsDefault = await page.getByLabel('Remove Duplicate Items').isChecked();
await page.getByLabel('Remove Duplicate Items').click();
await expect( page.getByLabel('Remove Duplicate Items').isChecked() ).resolves.toBe(!duplicatedItemsDefault);
// Change item counts setting.
await page.locator('#feedzy_item_limit').fill('3');
await expect( page.locator('#feedzy_item_limit').inputValue() ).resolves.toBe('3');
await page.getByRole('button', { name: 'Save & Activate importing' }).click({ force: true });
await runFeedImport( page );
await expect( page.locator('#ui-id-1').locator('li a').count() ).resolves.toBe(3);
});
test( 'chained actions for feed content', async({ editor, page, admin }) => {
await page.setViewportSize({
width: 1920,
height: 1080,
});
const importName = 'Test Title: changing General Feed Settings';
await page.goto('/wp-admin/post-new.php?post_type=feedzy_imports');
await tryCloseTourModal( page );
await page.getByPlaceholder('Add a name for your import').fill(importName);
await addFeeds( page, [FEED_URL] );
await page.getByRole('button', { name: 'Step 3 Map content' }).click({ force: true });
await page.getByRole('button', { name: 'Insert Tag' }).nth(2).click({ force: true });
await page.getByRole('link', { name: 'Item Content [#item_content]' }).click({ force: true });
// Add the first action.
await page.getByRole('button', { name: 'Add new' }).click({ force: true });
await page.getByText('Trim Content').click({ force: true });
await expect( page.getByRole('button', { name: 'Trim Content' }) ).toBeVisible();
await page.getByRole('button', { name: 'Trim Content' }).click({ force: true });
await page.getByPlaceholder('45').fill('10');
// Add the second action.
await page.getByRole('button', { name: 'Add new' }).click({ force: true });
await page.getByText('Search / Replace').click({ force: true });
await page.getByRole('button', { name: 'Search and Replace' }).click({ force: true });
await page.getByLabel('Search').fill('Lorem');
await page.getByLabel('Replace with').fill('Ipsum');
await page.getByRole('list').getByRole('button').nth(1).click({ force: true }); // Delete the first action.
await expect( page.getByRole('button', { name: 'Trim Content' }) ).toBeHidden();
await page.getByRole('button', { name: 'Save Actions' }).click({ force: true });
await expect( page.getByRole('heading', { name: 'Add actions to this tag' }) ).toBeHidden(); // The modal is closed.
await expect( page.getByTitle('item content').getByRole('link') ).toBeVisible(); // The action tag is added.
// Save the serialized actions in the input field.
const contentItemTagData = await page.locator('tag[title="item content"] .tagify__filter-icon').getAttribute('value');
await page.evaluate( (contentItemTagData) => {
document.querySelector('[name="feedzy_meta_data[import_post_content]"]').value = `[[{"value": "${contentItemTagData}"}]]`;
} , contentItemTagData);
await page.getByRole('button', { name: 'Save', exact: true }).click({ force: true });
await page.waitForSelector('#the-list', { timeout: 5000 });
const editLink = await page.locator('#the-list .row-actions .edit a').first().getAttribute('href');
await page.goto(editLink);
await page.getByRole('button', { name: 'Step 3 Map content' }).click({ force: true });
await page.getByTitle('remove tag').click({ force: true });
await expect( page.getByText('item content', { exact: true }) ).toBeHidden();
});
test( 'chained actions for feed title ', async({ editor, page, admin }) => {
await page.setViewportSize({
width: 1920,
height: 1080,
});
const importName = 'Test Title: changing General Feed Settings';
await page.goto('/wp-admin/post-new.php?post_type=feedzy_imports');
await tryCloseTourModal( page );
await page.getByPlaceholder('Add a name for your import').fill(importName);
await addFeeds( page, [FEED_URL] );
await page.getByRole('button', { name: 'Step 3 Map content' }).click({ force: true });
await page.locator('span').filter({ hasText: '[#item_title]' }).clear();
await page.getByRole('button', { name: 'Insert Tag' }).first().click({ force: true });
await page.getByRole('link', { name: 'Item Title [#item_title]' }).click({ force: true });
// Add the first action.
await page.getByRole('button', { name: 'Add new' }).click({ force: true });
await page.getByText('Trim Content').click({ force: true });
await expect( page.getByRole('button', { name: 'Trim Content' }) ).toBeVisible();
await page.getByRole('button', { name: 'Trim Content' }).click({ force: true });
await page.getByPlaceholder('45').fill('10');
// Add the second action.
await page.getByRole('button', { name: 'Add new' }).click({ force: true });
await page.getByText('Search / Replace').click({ force: true });
await page.getByRole('button', { name: 'Search and Replace' }).click({ force: true });
await page.getByLabel('Search').fill('Lorem');
await page.getByLabel('Replace with').fill('Ipsum');
await page.getByRole('button', { name: 'Save Actions' }).click({ force: true });
await expect( page.getByText('item title', { exact: true }) ).toBeVisible(); // The action tag is added.
// Save the serialized actions in the input field.
const titleItemTagData = await page.locator('tag[title="item title"] .tagify__filter-icon').getAttribute('value');
await page.evaluate( (titleItemTagData) => {
document.querySelector('[name="feedzy_meta_data[import_post_title]"]').value = `[[{"value": "${titleItemTagData}"}]]`;
}, titleItemTagData);
await page.getByRole('button', { name: 'Save', exact: true }).click({ force: true });
await page.waitForSelector('#the-list', { timeout: 5000 });
const editLink = await page.locator('#the-list .row-actions .edit a').first().getAttribute('href');
await page.goto(editLink);
await page.getByRole('button', { name: 'Step 3 Map content' }).click({ force: true });
await page.getByTitle('remove tag').click({ force: true });
await expect( page.getByText('item title', { exact: true }) ).toBeHidden();
} );
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Feed Edit page and reproduce the flaky interactions in the Playwright and Cypress examples, focusing on Tagify fields and the Save flow. Review the existing browser-test helpers and verify that injected values persist after saving and reopening the feed, with the listed assertions passing reliably.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cypress, javascript, php, playwright
- Domain
- frontend, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100