@@ -63,7 +63,10 @@ import {
6363 waitForAllLoadersToDisappear ,
6464} from '../../utils/entity' ;
6565import { visitServiceDetailsPage } from '../../utils/service' ;
66+ import { getCurrentMillis } from '../../utils/dateTime' ;
67+ import { clickDataQualityStatCard } from '../../utils/entityPanel' ;
6668import { PLAYWRIGHT_SAMPLE_DATA_TAG_OBJ } from '../../constant/config' ;
69+ import { Column , Table } from '../../../src/generated/entity/data/table' ;
6770
6871const entities = {
6972 'Api Endpoint' : ApiEndpointClass ,
@@ -1205,11 +1208,11 @@ Object.entries(entities).forEach(([key, EntityClass]) => {
12051208 await test . step (
12061209 'Verify array column with nested children renders correctly' ,
12071210 async ( ) => {
1208- const tableResponse = entity . entityResponseData as any ;
1211+ const tableResponse = entity . entityResponseData as Table ;
12091212 const columns = tableResponse ?. columns || [ ] ;
12101213
12111214 const nestedParent = columns . find (
1212- ( col : any ) => col . name === ( entity as TableClass ) . columnsName [ 2 ]
1215+ ( col : Column ) => col . name === ( entity as TableClass ) . columnsName [ 2 ]
12131216 ) ;
12141217
12151218 if ( ! nestedParent ) {
@@ -1223,7 +1226,7 @@ Object.entries(entities).forEach(([key, EntityClass]) => {
12231226 const nestedParentFQN = nestedParent . fullyQualifiedName ;
12241227
12251228 const arrayColumn = nestedParent . children ?. find (
1226- ( col : any ) => col . name === ( entity as TableClass ) . columnsName [ 4 ]
1229+ ( col : Column ) => col . name === ( entity as TableClass ) . columnsName [ 4 ]
12271230 ) ;
12281231
12291232 if ( ! arrayColumn ) {
@@ -1706,6 +1709,311 @@ Object.entries(entities).forEach(([key, EntityClass]) => {
17061709 ) ;
17071710 } ) ;
17081711 }
1712+
1713+ if ( entity . type === 'Table' ) {
1714+ test (
1715+ 'Column detail panel - Data Quality tab shows test cases' ,
1716+ async ( { page } ) => {
1717+ test . slow ( ) ;
1718+
1719+ const { apiContext, afterAction } = await getApiContext ( page ) ;
1720+ const tableEntity = entity as TableClass ;
1721+ const tableFQN =
1722+ entity . entityResponseData ?. [ 'fullyQualifiedName' ] ;
1723+ const columnName = tableEntity . columnsName [ 0 ] ;
1724+ let testCase1Name = '' ;
1725+ let testCase2Name = '' ;
1726+
1727+ try {
1728+ await tableEntity . createTestSuiteAndPipelines ( apiContext ) ;
1729+
1730+ const testCase1 = await tableEntity . createTestCase ( apiContext , {
1731+ name : `pw_col_dq_success_${ uuid ( ) } ` ,
1732+ entityLink : `<#E::table::${ tableFQN } ::columns::${ columnName } >` ,
1733+ testDefinition : 'columnValueLengthsToBeBetween' ,
1734+ parameterValues : [
1735+ { name : 'minLength' , value : 1 } ,
1736+ { name : 'maxLength' , value : 10 } ,
1737+ ] ,
1738+ } ) ;
1739+
1740+ const testCase2 = await tableEntity . createTestCase ( apiContext , {
1741+ name : `pw_col_dq_failed_${ uuid ( ) } ` ,
1742+ entityLink : `<#E::table::${ tableFQN } ::columns::${ columnName } >` ,
1743+ testDefinition : 'columnValueLengthsToBeBetween' ,
1744+ parameterValues : [
1745+ { name : 'minLength' , value : 100 } ,
1746+ { name : 'maxLength' , value : 200 } ,
1747+ ] ,
1748+ } ) ;
1749+
1750+ testCase1Name = testCase1 . name ;
1751+ testCase2Name = testCase2 . name ;
1752+
1753+ await tableEntity . addTestCaseResult (
1754+ apiContext ,
1755+ testCase1 . fullyQualifiedName ,
1756+ { testCaseStatus : 'Success' , timestamp : getCurrentMillis ( ) }
1757+ ) ;
1758+
1759+ await tableEntity . addTestCaseResult (
1760+ apiContext ,
1761+ testCase2 . fullyQualifiedName ,
1762+ {
1763+ testCaseStatus : 'Failed' ,
1764+ result : 'Column value length exceeded maximum' ,
1765+ timestamp : getCurrentMillis ( ) ,
1766+ }
1767+ ) ;
1768+
1769+ await test . step (
1770+ 'Open column detail panel and navigate to DQ tab' ,
1771+ async ( ) => {
1772+ await redirectToHomePage ( page ) ;
1773+ await entity . visitEntityPage ( page ) ;
1774+
1775+ await page . getByTestId ( entity . childrenTabId ?? '' ) . click ( ) ;
1776+ await waitForAllLoadersToDisappear ( page ) ;
1777+
1778+ await openColumnDetailPanel ( {
1779+ page,
1780+ rowSelector,
1781+ columnId : entity . childrenSelectorId ?? '' ,
1782+ columnNameTestId : 'column-name' ,
1783+ entityType : entity . type as EntityType ,
1784+ } ) ;
1785+
1786+ const dqTabResponsePromise = page . waitForResponse (
1787+ ( response ) =>
1788+ response
1789+ . url ( )
1790+ . includes ( '/api/v1/dataQuality/testCases' )
1791+ ) ;
1792+ await page . getByTestId ( 'data-quality-tab' ) . click ( ) ;
1793+ const dqTabResponse = await dqTabResponsePromise ;
1794+ expect ( dqTabResponse . status ( ) ) . toBe ( 200 ) ;
1795+ await waitForAllLoadersToDisappear ( page ) ;
1796+ }
1797+ ) ;
1798+
1799+ await test . step (
1800+ 'Verify stat cards and filter by failed' ,
1801+ async ( ) => {
1802+ const panelContainer = page . locator ( '.column-detail-panel' ) ;
1803+ const dqContent = panelContainer . locator (
1804+ '.data-quality-tab-container'
1805+ ) ;
1806+
1807+ await expect ( dqContent ) . toBeVisible ( ) ;
1808+
1809+ const successStat = panelContainer . locator (
1810+ '[data-testid="data-quality-stat-card-success"]'
1811+ ) ;
1812+ const failedStat = panelContainer . locator (
1813+ '[data-testid="data-quality-stat-card-failed"]'
1814+ ) ;
1815+
1816+ await expect ( successStat ) . toBeVisible ( ) ;
1817+ await expect ( failedStat ) . toBeVisible ( ) ;
1818+
1819+ await expect ( successStat ) . toHaveText ( '1Passed' ) ;
1820+ await expect ( failedStat ) . toHaveText ( '1Failed' ) ;
1821+
1822+ await clickDataQualityStatCard ( page , 'failed' ) ;
1823+
1824+ const testCaseCardsSection = dqContent . locator (
1825+ '.test-case-cards-section'
1826+ ) ;
1827+
1828+ await expect ( testCaseCardsSection ) . toBeVisible ( ) ;
1829+
1830+ const failedCards =
1831+ testCaseCardsSection . locator ( '.test-case-card' ) ;
1832+
1833+ await expect ( failedCards ) . toHaveCount ( 1 ) ;
1834+
1835+ const failedCard = failedCards . first ( ) ;
1836+
1837+ await expect (
1838+ failedCard . locator ( '.test-case-name' )
1839+ ) . toContainText ( testCase2Name ) ;
1840+
1841+ }
1842+ ) ;
1843+
1844+ await test . step (
1845+ 'Filter by success and verify test case card' ,
1846+ async ( ) => {
1847+ const panelContainer = page . locator ( '.column-detail-panel' ) ;
1848+ const dqContent = panelContainer . locator (
1849+ '.data-quality-tab-container'
1850+ ) ;
1851+ await clickDataQualityStatCard ( page , 'success' ) ;
1852+
1853+ const testCaseCardsSection = dqContent . locator (
1854+ '.test-case-cards-section'
1855+ ) ;
1856+ const successCards =
1857+ testCaseCardsSection . locator ( '.test-case-card' ) ;
1858+
1859+ await expect ( successCards ) . toHaveCount ( 1 ) ;
1860+ await expect (
1861+ successCards . first ( ) . locator ( '.test-case-name' )
1862+ ) . toContainText ( testCase1Name ) ;
1863+
1864+ await closeColumnDetailPanel ( page ) ;
1865+ }
1866+ ) ;
1867+ } finally {
1868+ await afterAction ( ) ;
1869+ }
1870+ }
1871+ ) ;
1872+
1873+ test (
1874+ 'Column detail panel - Data Quality Incidents tab' ,
1875+ async ( { page } ) => {
1876+ test . slow ( ) ;
1877+
1878+ const { apiContext, afterAction } = await getApiContext ( page ) ;
1879+ const tableEntity = entity as TableClass ;
1880+ const tableFQN =
1881+ entity . entityResponseData ?. [ 'fullyQualifiedName' ] ;
1882+ const columnName = tableEntity . columnsName [ 0 ] ;
1883+
1884+ try {
1885+ await tableEntity . createTestSuiteAndPipelines ( apiContext ) ;
1886+
1887+ const testCase = await tableEntity . createTestCase ( apiContext , {
1888+ name : `pw_col_incident_${ uuid ( ) } ` ,
1889+ entityLink : `<#E::table::${ tableFQN } ::columns::${ columnName } >` ,
1890+ testDefinition : 'columnValueLengthsToBeBetween' ,
1891+ parameterValues : [
1892+ { name : 'minLength' , value : 100 } ,
1893+ { name : 'maxLength' , value : 200 } ,
1894+ ] ,
1895+ } ) ;
1896+
1897+ await tableEntity . addTestCaseResult (
1898+ apiContext ,
1899+ testCase . fullyQualifiedName ,
1900+ {
1901+ testCaseStatus : 'Failed' ,
1902+ result : 'Column value length exceeded maximum' ,
1903+ timestamp : getCurrentMillis ( ) ,
1904+ }
1905+ ) ;
1906+
1907+ await test . step (
1908+ 'Open column detail panel and navigate to Incidents tab' ,
1909+ async ( ) => {
1910+ await redirectToHomePage ( page ) ;
1911+ await entity . visitEntityPage ( page ) ;
1912+
1913+ await page . getByTestId ( entity . childrenTabId ?? '' ) . click ( ) ;
1914+ await waitForAllLoadersToDisappear ( page ) ;
1915+
1916+ await openColumnDetailPanel ( {
1917+ page,
1918+ rowSelector,
1919+ columnId : entity . childrenSelectorId ?? '' ,
1920+ columnNameTestId : 'column-name' ,
1921+ entityType : entity . type as EntityType ,
1922+ } ) ;
1923+
1924+ const dqTabResponsePromise = page . waitForResponse (
1925+ ( response ) =>
1926+ response
1927+ . url ( )
1928+ . includes ( '/api/v1/dataQuality/testCases' )
1929+ ) ;
1930+ await page . getByTestId ( 'data-quality-tab' ) . click ( ) ;
1931+ const dqTabResponse = await dqTabResponsePromise ;
1932+ expect ( dqTabResponse . status ( ) ) . toBe ( 200 ) ;
1933+
1934+ await waitForAllLoadersToDisappear ( page ) ;
1935+
1936+ const dqContent = page
1937+ . locator ( '.column-detail-panel' )
1938+ . locator ( '.data-quality-tab-container' ) ;
1939+
1940+ await expect ( dqContent ) . toBeVisible ( ) ;
1941+
1942+
1943+ await dqContent
1944+ . locator ( '.data-quality-tabs' )
1945+ . getByRole ( 'tab' , { name : / i n c i d e n t s / i } )
1946+ . click ( ) ;
1947+ await waitForAllLoadersToDisappear ( page ) ;
1948+ }
1949+ ) ;
1950+
1951+ await test . step (
1952+ 'Verify incidents stats container and cards' ,
1953+ async ( ) => {
1954+ const panelContainer = page . locator ( '.column-detail-panel' ) ;
1955+ const dqContent = panelContainer . locator (
1956+ '.data-quality-tab-container'
1957+ ) ;
1958+ const incidentsTabContent = dqContent . locator (
1959+ '.incidents-tab-content'
1960+ ) ;
1961+
1962+ await expect ( incidentsTabContent ) . toBeVisible ( ) ;
1963+
1964+ const incidentStatsContainer = incidentsTabContent . locator (
1965+ '.incidents-stats-container'
1966+ ) ;
1967+
1968+ await expect ( incidentStatsContainer ) . toBeVisible ( ) ;
1969+
1970+ await expect (
1971+ incidentStatsContainer . locator (
1972+ '.incident-stat-card.new-card'
1973+ )
1974+ ) . toBeVisible ( ) ;
1975+ await expect (
1976+ incidentStatsContainer . locator (
1977+ '.incident-stat-card.ack-card'
1978+ )
1979+ ) . toBeVisible ( ) ;
1980+ await expect (
1981+ incidentStatsContainer . locator (
1982+ '.incident-stat-card.assigned-card'
1983+ )
1984+ ) . toBeVisible ( ) ;
1985+ await expect (
1986+ incidentStatsContainer . locator ( '.resolved-section' )
1987+ ) . toBeVisible ( ) ;
1988+
1989+ const incidentCardsSection = incidentsTabContent . locator (
1990+ '.incident-cards-section'
1991+ ) ;
1992+
1993+ await expect ( incidentCardsSection ) . toBeVisible ( ) ;
1994+
1995+ const incidentCards =
1996+ incidentCardsSection . locator ( '.test-case-card' ) ;
1997+ const cardCount = await incidentCards . count ( ) ;
1998+
1999+ if ( cardCount > 0 ) {
2000+ const assigneeSection = incidentCards
2001+ . first ( )
2002+ . locator ( '.test-case-detail-item' )
2003+ . filter ( { hasText : / a s s i g n e e / i } ) ;
2004+
2005+ await expect ( assigneeSection ) . toBeVisible ( ) ;
2006+ }
2007+
2008+ await closeColumnDetailPanel ( page ) ;
2009+ }
2010+ ) ;
2011+ } finally {
2012+ await afterAction ( ) ;
2013+ }
2014+ }
2015+ ) ;
2016+ }
17092017 }
17102018
17112019 /**
0 commit comments