diff --git a/tests/System/integration/site/components/com_content/Category.cy.js b/tests/System/integration/site/components/com_content/Category.cy.js index 5ae782476b634..021f90bbad1d8 100644 --- a/tests/System/integration/site/components/com_content/Category.cy.js +++ b/tests/System/integration/site/components/com_content/Category.cy.js @@ -1,4 +1,10 @@ describe('Test in frontend that the content category view', () => { + afterEach(() => { + cy.db_updateExtensionParameter('filter_field', 'hide', 'com_content'); + cy.db_updateExtensionParameter('list_show_author', '1', 'com_content'); + cy.db_updateExtensionParameter('list_show_hits', '1', 'com_content'); + }); + ['default', 'blog'].forEach((layout) => { it(`can display a list of articles in the ${layout} layout in a menu item`, () => { cy.db_createArticle({ title: 'article 1' }) @@ -38,6 +44,321 @@ describe('Test in frontend that the content category view', () => { }); }); + it('can use the title filter to narrow the article list', () => { + cy.db_createArticle({ title: 'article abc 1' }) + .then((article) => cy.db_createArticle({ title: 'article def 2', catid: article.catid })) + .then((article) => cy.db_createArticle({ title: 'article abc 3', catid: article.catid })) + .then((article) => cy.db_createArticle({ title: 'article xyz 4', catid: article.catid })) + .then((article) => cy.db_createArticle({ title: 'article def 5', catid: article.catid })) + .then((article) => cy.db_createMenuItem({ + title: 'automated test', + alias: 'automated-test', + path: 'automated-test', + link: `index.php?option=com_content&view=category&id=${article.catid}`, + params: { + filter_field: 'title', + list_show_author: '0', + }, + })) + .then(() => { + cy.visit('/'); + cy.get('a:contains(automated test)').click(); + cy.get('main div.com-content-category.category-list').within(() => { + cy.get('table.com-content-category__table thead th').should('have.length', 2); + cy.get('table.com-content-category__table thead th').eq(0).should('contain.text', 'Title'); + cy.get('table.com-content-category__table thead th').eq(1).should('contain.text', 'Hits'); + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article abc 1') + .should('contain.text', 'article def 2') + .should('contain.text', 'article abc 3') + .should('contain.text', 'article xyz 4') + .should('contain.text', 'article def 5'); + + cy.get('#filter-search').should('have.attr', 'placeholder', 'Title Filter'); + cy.get('#filter-search').clear().type('abc'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article abc 1') + .should('not.contain.text', 'article def 2') + .should('contain.text', 'article abc 3') + .should('not.contain.text', 'article xyz 4') + .should('not.contain.text', 'article def 5'); + + cy.get('#filter-search').clear().type('xyz'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article abc 1') + .should('not.contain.text', 'article def 2') + .should('not.contain.text', 'article abc 3') + .should('contain.text', 'article xyz 4') + .should('not.contain.text', 'article def 5'); + + cy.get('#filter-search').clear().type('def'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article abc 1') + .should('contain.text', 'article def 2') + .should('not.contain.text', 'article abc 3') + .should('not.contain.text', 'article xyz 4') + .should('contain.text', 'article def 5'); + + cy.get('.com-content__filter button[type="reset"]').click(); + cy.get('#filter-search').should('have.value', ''); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article abc 1') + .should('contain.text', 'article def 2') + .should('contain.text', 'article abc 3') + .should('contain.text', 'article xyz 4') + .should('contain.text', 'article def 5'); + }); + }); + }); + + it('can use the author filter to narrow the article list', () => { + cy.db_createArticle({ title: 'article 1', created_by_alias: 'James' }) + .then((article) => cy.db_createArticle({ title: 'article 2', catid: article.catid, created_by_alias: 'William' })) + .then((article) => cy.db_createArticle({ title: 'article 3', catid: article.catid, created_by_alias: 'Emma' })) + .then((article) => { + cy.db_createUser({ name: 'Emma' }).then((id) => { + cy.db_createArticle({ title: 'article 4', catid: article.catid, created_by: id }); + cy.db_createArticle({ title: 'article 5', catid: article.catid, created_by: id, created_by_alias: 'Charlotte' }); + }); + }) + .then((article) => cy.db_createMenuItem({ + title: 'automated test', + alias: 'automated-test', + path: 'automated-test', + link: `index.php?option=com_content&view=category&id=${article.catid}`, + params: { + filter_field: '', + list_show_date: 'published', + }, + })) + .then(() => { + cy.db_updateExtensionParameter('filter_field', 'author', 'com_content'); + cy.db_updateExtensionParameter('list_show_hits', '0', 'com_content'); + cy.visit('/'); + cy.get('a:contains(automated test)').click(); + cy.get('main div.com-content-category.category-list').within(() => { + cy.get('table.com-content-category__table thead th').should('have.length', 3); + cy.get('table.com-content-category__table thead th').eq(0).should('contain.text', 'Title'); + cy.get('table.com-content-category__table thead th').eq(1).should('contain.text', 'Published Date'); + cy.get('table.com-content-category__table thead th').eq(2).should('contain.text', 'Author'); + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + + cy.get('#filter-search').should('have.attr', 'placeholder', 'Author Filter'); + cy.get('#filter-search').clear().type('william'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('not.contain.text', 'article 3') + .should('not.contain.text', 'article 4') + .should('not.contain.text', 'article 5'); + + cy.get('#filter-search').clear().type('James'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('not.contain.text', 'article 2') + .should('not.contain.text', 'article 3') + .should('not.contain.text', 'article 4') + .should('not.contain.text', 'article 5'); + + cy.get('#filter-search').clear().type('Charlotte'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('not.contain.text', 'article 2') + .should('not.contain.text', 'article 3') + .should('not.contain.text', 'article 4') + .should('contain.text', 'article 5'); + + cy.get('#filter-search').clear().type('emma'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('not.contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('not.contain.text', 'article 5'); + + cy.get('.com-content__filter button[type="reset"]').click(); + cy.get('#filter-search').should('have.value', ''); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + }); + }); + }); + + it('can use the tag filter to narrow the article list', () => { + cy.db_createArticle({ title: 'article 1' }) + .then((article) => { + cy.db_createTag({ title: 'tag1' }).then((id) => { + cy.db_createArticle({ title: 'article 2', catid: article.catid, tags: [id] }); + cy.db_createArticle({ title: 'article 3', catid: article.catid, tags: [id] }); + }); + }) + .then((article) => { + cy.db_createTag({ title: 'tag2' }).then((id) => { + cy.db_createArticle({ title: 'article 4', catid: article.catid, tags: [id] }); + cy.db_createArticle({ title: 'article 5', catid: article.catid, tags: [id] }); + }); + }) + .then((article) => cy.db_createMenuItem({ + title: 'automated test', + alias: 'automated-test', + path: 'automated-test', + link: `index.php?option=com_content&view=category&id=${article.catid}`, + params: { + filter_field: 'tag', + }, + })) + .then(() => { + cy.visit('/'); + cy.get('a:contains(automated test)').click(); + cy.get('main div.com-content-category.category-list').within(() => { + cy.get('table.com-content-category__table thead th').should('have.length', 3); + cy.get('table.com-content-category__table thead th').eq(0).should('contain.text', 'Title'); + cy.get('table.com-content-category__table thead th').eq(1).should('contain.text', 'Author'); + cy.get('table.com-content-category__table thead th').eq(2).should('contain.text', 'Hits'); + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + + cy.get('#filter-search').select('tag1'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('not.contain.text', 'article 4') + .should('not.contain.text', 'article 5'); + + cy.get('#filter-search').select('tag2'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('not.contain.text', 'article 2') + .should('not.contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + + cy.get('.com-content__filter button[type="reset"]').click(); + cy.get('#filter-search').should('have.value', ''); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + }); + }); + }); + + it('can use the month filter to narrow the article list', () => { + cy.db_createArticle({ title: 'article 1', publish_up: '2026-08-17 20:00:00' }) + .then((article) => cy.db_createArticle({ title: 'article 2', catid: article.catid, publish_up: '2026-08-28 20:00:00' })) + .then((article) => cy.db_createArticle({ title: 'article 3', catid: article.catid, publish_up: '2026-05-20 20:00:00' })) + .then((article) => cy.db_createArticle({ title: 'article 4', catid: article.catid, publish_up: '2026-05-25 20:00:00' })) + .then((article) => cy.db_createArticle({ title: 'article 5', catid: article.catid, publish_up: '2025-08-17 20:00:00' })) + .then((article) => cy.db_createMenuItem({ + title: 'automated test', + alias: 'automated-test', + path: 'automated-test', + link: `index.php?option=com_content&view=category&id=${article.catid}`, + params: { + filter_field: 'month', + list_show_date: 'modified', + list_show_hits: '0', + }, + })) + .then(() => { + cy.db_updateExtensionParameter('filter_field', 'hits', 'com_content'); + cy.db_updateExtensionParameter('list_show_author', '0', 'com_content'); + cy.visit('/'); + cy.get('a:contains(automated test)').click(); + cy.get('main div.com-content-category.category-list').within(() => { + cy.get('table.com-content-category__table thead th').should('have.length', 2); + cy.get('table.com-content-category__table thead th').eq(0).should('contain.text', 'Title'); + cy.get('table.com-content-category__table thead th').eq(1).should('contain.text', 'Modified Date'); + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + + cy.get('#filter-search').select('2026-08-01'); + cy.get('#filter-search option:selected').should('have.text', 'August 2026 [2]'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('not.contain.text', 'article 3') + .should('not.contain.text', 'article 4') + .should('not.contain.text', 'article 5'); + + cy.get('#filter-search').select('2025-08-01'); + cy.get('#filter-search option:selected').should('have.text', 'August 2025 [1]'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('not.contain.text', 'article 2') + .should('not.contain.text', 'article 3') + .should('not.contain.text', 'article 4') + .should('contain.text', 'article 5'); + + cy.get('#filter-search').select('2026-05-01'); + cy.get('#filter-search option:selected').should('have.text', 'May 2026 [2]'); + cy.get('.com-content__filter button[type="submit"]').click(); + + cy.get('table.com-content-category__table tbody th a') + .should('not.contain.text', 'article 1') + .should('not.contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('not.contain.text', 'article 5'); + + cy.get('.com-content__filter button[type="reset"]').click(); + cy.get('#filter-search').should('have.value', ''); + + cy.get('table.com-content-category__table tbody th a') + .should('contain.text', 'article 1') + .should('contain.text', 'article 2') + .should('contain.text', 'article 3') + .should('contain.text', 'article 4') + .should('contain.text', 'article 5'); + }); + }); + }); + it('can open the article form in the default layout', () => { cy.db_createArticle({ title: 'article 1' }) .then((article) => cy.db_createMenuItem({ diff --git a/tests/System/plugins/db.mjs b/tests/System/plugins/db.mjs index e8bdcbff02f00..c09e6a70da014 100644 --- a/tests/System/plugins/db.mjs +++ b/tests/System/plugins/db.mjs @@ -170,6 +170,7 @@ function deleteInsertedItems(config) { if (item.table === `${config.env.db_prefix}content`) { promises.push(queryTestDB(`DELETE FROM #__content_frontpage WHERE content_id IN (${item.rows.join(',')})`, config)); + promises.push(queryTestDB(`DELETE FROM #__contentitem_tag_map WHERE content_item_id IN (${item.rows.join(',')}) AND type_alias = 'com_content.article'`, config)); promises.push(queryTestDB(`DELETE FROM #__workflow_associations WHERE item_id IN (${item.rows.join(',')}) AND extension = 'com_content.article'`, config)); } diff --git a/tests/System/support/commands/db.mjs b/tests/System/support/commands/db.mjs index c30e92958f582..5048db4958a92 100644 --- a/tests/System/support/commands/db.mjs +++ b/tests/System/support/commands/db.mjs @@ -113,6 +113,9 @@ Cypress.Commands.add('db_createArticle', (articleData) => { metadata: '', }; + const tags = articleData.tags ?? []; + delete articleData.tags; + const article = { ...defaultArticleOptions, ...articleData }; return getDefaultCategoryId('com_content') @@ -128,6 +131,9 @@ Cypress.Commands.add('db_createArticle', (articleData) => { if (article.featured === 1) { await cy.task('queryDB', `INSERT INTO #__content_frontpage (content_id, ordering) VALUES ('${article.id}', '1')`); } + tags.forEach(async (tag) => { + await cy.task('queryDB', `INSERT INTO #__contentitem_tag_map (type_alias, core_content_id, content_item_id, tag_id, tag_date, type_id) VALUES ('com_content.article', '0', '${article.id}', '${tag}', '2026-08-29 11:00:00', '1')`); + }); await cy.task('queryDB', `INSERT INTO #__workflow_associations (item_id, stage_id, extension) VALUES (${article.id}, 1, 'com_content.article')`); return article; @@ -504,6 +510,11 @@ Cypress.Commands.add('db_createMenuItem', (menuItemData) => { defaultMenuItemOptions.rgt = myrgt[0].rgt + 1; const menuItem = { ...defaultMenuItemOptions, ...menuItemData }; + ['params'].forEach((key) => { + if (typeof menuItem[key] === 'object') { + menuItem[key] = JSON.stringify(menuItem[key]); + } + }); // Extract the component from the link const component = (new URLSearchParams(menuItem.link.replace('index.php', ''))).get('option'); return cy.task('queryDB', `SELECT extension_id FROM #__extensions WHERE name = '${component}'`).then((id) => {