Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions cypress/RoadmapPage.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import RoadmapPage from './pages/RoadmapPage';

describe('RoadMap Page Navigation and Functionality', () => {
let roadmapPage;

beforeEach(() => {
roadmapPage = new RoadmapPage();
roadmapPage.visit();
});

it('User navigates to the RoadMap Page and verifies the header', () => {
roadmapPage.verifyPageLoaded();
});

it('User clicks on the community page link and verifies navigation', () => {
roadmapPage.verifyCommunityLink();
});
Comment on lines +15 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Test name claims navigation, but no click/navigation is performed.
Either update the test name or add the click + URL assertion.

✏️ Suggested rename (minimal change)
-  it('User clicks on the community page link and verifies navigation', () => {
+  it('User verifies the community page link URL', () => {
     roadmapPage.verifyCommunityLink();
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('User clicks on the community page link and verifies navigation', () => {
roadmapPage.verifyCommunityLink();
});
it('User verifies the community page link URL', () => {
roadmapPage.verifyCommunityLink();
});
🤖 Prompt for AI Agents
In `@cypress/RoadmapPage.cy.js` around lines 15 - 17, The test title says it
verifies navigation but only calls roadmapPage.verifyCommunityLink() without
performing a click or asserting the URL; either rename the test to reflect a
non-navigation check or update the test to perform the navigation and assertion
by invoking the click and URL assertion (e.g., add a call to a click method such
as roadmapPage.clickCommunityLink() or implement the click inside
verifyCommunityLink(), then assert cy.url().should('include', '/community') or
the expected path). Ensure the chosen change updates the test name if you keep
it as a non-navigation check or implements both the click and URL assertion when
keeping the current name.


const tooltips = [
{ name: 'Outcome', index: 0 },
{ name: 'Solution', index: 1 },
{ name: 'Implementation', index: 2 }
];

tooltips.forEach(({ name, index }) => {
it(`User verifies ${name} tooltip`, () => {
roadmapPage.verifyTooltip(index);
});
});
});
42 changes: 42 additions & 0 deletions cypress/casestudies.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import CaseStudiesPage from './pages/CaseStudiesPage';
import { verifyLinks } from './support/helpers';

let casestudiespage;

beforeEach(() => {
casestudiespage = new CaseStudiesPage();
casestudiespage.visit();
});

describe('Critical User Flows in CaseStudies Page', () => {
const verifications = [
{ name: 'header', testName: 'User navigates to the Case Studies Page and verifies the header', fn: () => casestudiespage.verifyHeader() },
{ name: 'FAQ link', testName: 'User verifies FAQ link is visible and contains correct URL', fn: () => casestudiespage.verifyFaqLink() },
{ name: 'Cards link', testName: 'User verifies Cards link is visible and contains correct URL', fn: () => casestudiespage.verifyCardsLink() },
{ name: 'Submit PR link', testName: 'User verifies Submit a Pull Request Link is visible and contains correct URL', fn: () => casestudiespage.verifySubmitPullRequestLink() }
];

verifications.forEach(({ testName, fn }) => {
it(testName, fn);
});
});

describe('Adopters Table', () => {
it('Navigates to the Case Studies page and scrolls down to the Adopters Table', () => {
casestudiespage.verifyScrollDown();
});
});

describe('Links under Resources Section', () => {
let links;

before(() => {
cy.fixture('caseStudiesLinks').then((data) => {
links = data;
});
});

it('Verifies all Links under Resources work', () => {
verifyLinks(links, (href, label) => casestudiespage.verifyResourceLink(href), 'href', 'label');
});
});
82 changes: 82 additions & 0 deletions cypress/fixtures/caseStudiesLinks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
[
{
"href": "https://www.youtube.com/watch?v=_MwzLZMwFN8",
"label": "Video: Raiffeisen Bank - GitOps with AsyncAPI"
},
{
"href": "https://www.youtube.com/watch?v=m8I0fYjx6Cc",
"label": "Video: LEGO Group - Documentation as Configuration"
},
{
"href": "https://www.youtube.com/watch?v=qjarcJQVLOg",
"label": "Video: LEGO Group - Cross-Domain Events"
},
{
"href": "https://www.confluent.io/events/kafka-summit-apac-2021/self-service-events-and-decentralised-governance-with-asyncapi-a-real-world/",
"label": "Video: Bank of New Zealand - Self-service Events"
},
{
"href": "https://www.youtube.com/watch?v=yjHgT0n2BtA",
"label": "Video: Zora Robotics - MQTT APIs for IoT"
},
{
"href": "https://www.youtube.com/watch?v=SxTpGRaNIPo",
"label": "Video: Walmart and eBay - AsyncAPI Specification"
},
{
"href": "https://www.youtube.com/watch?v=0_7QZyKLPoE",
"label": "Video: Postman - Synapse Event Infrastructure"
},
{
"href": "https://drive.google.com/file/d/1AVCG9_fFtuOtrvZVZWENmU2aDT7C51Jr/view?usp=sharing",
"label": "Slides: Adobe - AsyncAPI and Modelina"
},
{
"href": "https://www.youtube.com/watch?v=m4KS6FSeTT4",
"label": "Video: Open University of Catalonia - Smart Ports"
},
{
"href": "https://www.youtube.com/watch?v=CGLlxYy66LY",
"label": "Video: Oracle - Data Replication"
},
{
"href": "https://www.asyncapi.com/blog/transfergo-asyncapi-story",
"label": "Article: TransferGo - AsyncAPI Story"
},
{
"href": "https://drive.google.com/file/d/1y67PI8NaITPPwZAiDF2Zs7ISfcIpqMV8/view?usp=sharing",
"label": "Slides: Kuehne+Nagel - GitOps for Kafka"
},
{
"href": "https://adidas.gitbook.io/api-guidelines/asynchronous-api-guidelines/kafka-asynchronous-guidelines/a_introduction/why-asyncapi",
"label": "Docs: Adidas - API Guidelines"
},
{
"href": "https://drive.google.com/file/d/1YzLwQZsMUXGwj_Lsqv-ZnvV2knuowWrS/view?usp=drive_link",
"label": "Slides: Morgan Stanley - WebSocket APIs"
},
{
"href": "https://www.asyncapi.com/casestudies/adeogroup",
"label": "Use Case: Adeo - Documentation Standards"
},
{
"href": "https://www.asyncapi.com/casestudies/hdiglobal",
"label": "Use Case: HDI Global SE - Documentation"
},
{
"href": "https://www.youtube.com/watch?v=KcYiD67gEh0&list=PLbi1gRlP7pig_nA0tRlr0hU_h5sB2HXcq&index=6",
"label": "Video: SAP - Event Catalog"
},
{
"href": "https://www.slideshare.net/slideshow/apidays-paris-2022-adding-a-mock-as-a-service-capability-to-your-api-strategy-portfolio-ludovic-pourrat-lombard-odier/255041645#4",
"label": "Slides: Lombard Odier - Mock as a Service"
},
{
"href": "https://github.com/siemens/rosita",
"label": "Code: Siemens AG - ROS2 Interfaces"
},
{
"href": "https://github.com/pagopa/p4pa-registries/blob/develop/asyncapi/generated.asyncapi.json",
"label": "Code: PagoPA - Event-Driven APIs"
}
]
36 changes: 36 additions & 0 deletions cypress/pages/BasePage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class BasePage {
visit(path = '/') {
cy.visit(path);
return this;
}

verifyHeadingExists(headingText, tag = 'h1') {
cy.get(tag).should('contain.text', headingText);
}

verifyElementIsVisible(selector) {
cy.get(selector).should('be.visible');
}

verifyElementHasAttribute(selector, attribute, value) {
cy.get(selector).should('have.attr', attribute, value);
}

scrollToText(text) {
cy.contains(text).scrollIntoView();
}

verifyButtonLink(href, text) {
cy.contains('a', text)
.should('have.attr', 'href', href)
.should('be.visible');
}

verifyLink(href, text) {
cy.get(`a[href="${href}"]`)
.should('be.visible')
.and('contain.text', text);
}
}

export default BasePage;
55 changes: 53 additions & 2 deletions cypress/pages/CaseStudiesPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,57 @@
class CaseStudiesPage {
import BasePage from './BasePage';

class CaseStudiesPage extends BasePage {
visit() {
super.visit('/casestudies');
}

verifyPageLoaded() {
cy.contains('h1', 'Case Studies').should('be.visible');
this.verifyHeadingExists('Case Studies', 'h1');
}

verifyHeader() {
this.verifyPageLoaded();
}

verifyScrollDown() {
this.scrollToText('Adopters');
}

verifyCardLink(cardName, cardUrl, index = 0) {
cy.get('[data-testid="CaseStudyCard-main"]')
.eq(index)
.within(() => {
cy.get(`img[alt*="${cardName.split(' ')[0]}"]`).should('exist');
})
.closest('a')
.should('have.attr', 'href', cardUrl);
}
Comment on lines +20 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find test files that call verifyCardLink
rg "verifyCardLink" --type js -B 2 -A 2

Repository: asyncapi/website

Length of output: 1169


🏁 Script executed:

# Look at the CaseStudyCard component to see how href is rendered
fd "CaseStudyCard" --type f

Repository: asyncapi/website

Length of output: 88


🏁 Script executed:

# Check the CaseStudiesPage.js file to understand the context better
cat -n cypress/pages/CaseStudiesPage.js | head -50

Repository: asyncapi/website

Length of output: 1499


🏁 Script executed:

cat -n components/CaseStudyCard.tsx

Repository: asyncapi/website

Length of output: 1652


🏁 Script executed:

# Check for Next.js config and any route handling
fd "next.config" -o "middleware" -o "routes" --type f | head -20

Repository: asyncapi/website

Length of output: 199


🏁 Script executed:

# Search for other href patterns in the codebase to see if leading slashes are used
rg "href=" --type tsx --type jsx -o | sort | uniq | head -30

Repository: asyncapi/website

Length of output: 87


🏁 Script executed:

# Check if there's any Link component wrapper or routing transformation
rg "next/link" -A 3 -B 1 --type tsx --type jsx | head -50

Repository: asyncapi/website

Length of output: 87


🏁 Script executed:

# Search for href patterns more broadly
rg "href=" -A 1 -B 1 | grep -E "href=.*casestudies|href=.*/" | head -20

Repository: asyncapi/website

Length of output: 2007


🏁 Script executed:

# Check for Next.js configuration
find . -name "next.config*" -o -name "tsconfig.json" | head -10

Repository: asyncapi/website

Length of output: 93


🏁 Script executed:

# Check what actual href values are being used in the codebase
rg "href=" -o | sort | uniq -c | sort -rn | head -20

Repository: asyncapi/website

Length of output: 1006


🏁 Script executed:

# Check for any routing middleware or href transformation
rg "casestudies" -B 2 -A 2 | head -40

Repository: asyncapi/website

Length of output: 2844


🏁 Script executed:

# Look at the test file itself to see if there are any patterns of href matching failures
fd "casestud.*\.cy\." -o "casestud.*spec\."

Repository: asyncapi/website

Length of output: 211


🏁 Script executed:

# Search for any href-related test utilities or assertions
rg "have\.attr.*href" | head -15

Repository: asyncapi/website

Length of output: 484


Make card href assertion resilient to leading slash / absolute URLs.
The exact have.attr(..., cardUrl) assertion can fail if the DOM renders /casestudies/... or a full origin. Prefer an include check for stability.

🔧 Suggested fix
-      .should('have.attr', 'href', cardUrl);
+      .should('have.attr', 'href')
+      .and('include', cardUrl);
🤖 Prompt for AI Agents
In `@cypress/pages/CaseStudiesPage.js` around lines 20 - 28, The href assertion in
verifyCardLink is brittle because have.attr(..., cardUrl) fails when the DOM
returns a leading-slash path or a full absolute URL; update verifyCardLink to
retrieve the anchor href and assert it includes the expected cardUrl (or
normalize by stripping origin/leading slash) instead of exact equality—locate
the verifyCardLink method and replace the final .should('have.attr', 'href',
cardUrl) with a resilient check that uses include (or a normalized comparison)
so both "/casestudies/..." and "https://.../casestudies/..." pass.


verifyResourceLink(href) {
cy.get(`a[href="${href}"]`)
.first()
.should('exist')
.should('have.attr', 'href', href);
}

verifyFaqLink() {
this.verifyButtonLink(
'https://github.com/asyncapi/website/blob/master/README.md#case-studies',
'FAQ'
);
}

verifySubmitPullRequestLink() {
this.verifyButtonLink(
'https://github.com/asyncapi/website/blob/master/config/usecases.yaml',
'submit a pull request'
);
}

verifyCardsLink() {
this.verifyCardLink('Adeo Group', 'casestudies/adeogroup', 0);
this.verifyCardLink('HDI Global SE', 'casestudies/hdiglobal', 1);
}
}

export default CaseStudiesPage;
31 changes: 29 additions & 2 deletions cypress/pages/RoadmapPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
class RoadmapPage {
import BasePage from './BasePage';

class RoadmapPage extends BasePage {
visit() {
super.visit('/roadmap');
}

verifyPageLoaded() {
cy.contains('h1', 'AsyncAPI becomes the #1 API specification for defining and developing APIs.').should('be.visible');
this.verifyHeadingExists(
'AsyncAPI becomes the #1 API specification for defining and developing APIs.',
'h1'
);
}

verifyHeader() {
this.verifyPageLoaded();
}

verifyCommunityLink() {
this.verifyElementHasAttribute(
'[data-testid="TextLink-href"]',
'href',
'https://github.com/asyncapi/community'
);
}

verifyTooltip(index) {
cy.get('[data-testid="InlineHelp-icon"]').eq(index).trigger('mouseover');
cy.get('[data-testid="InlineHelp"]').should('be.visible');
Comment on lines +27 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "RoadmapPage.js" | head -20

Repository: asyncapi/website

Length of output: 90


🏁 Script executed:

cat -n cypress/pages/RoadmapPage.js | head -50

Repository: asyncapi/website

Length of output: 997


🏁 Script executed:

rg "InlineHelp" cypress/pages/RoadmapPage.js -n

Repository: asyncapi/website

Length of output: 206


🏁 Script executed:

rg "data-testid" cypress/pages/RoadmapPage.js -B2 -A2 | head -100

Repository: asyncapi/website

Length of output: 396


🏁 Script executed:

rg "verifyTooltip" cypress/ -B2 -A2 | head -50

Repository: asyncapi/website

Length of output: 652


🏁 Script executed:

rg "InlineHelp" cypress/ -l

Repository: asyncapi/website

Length of output: 88


🏁 Script executed:

cat -n cypress/RoadmapPage.cy.js

Repository: asyncapi/website

Length of output: 1021


Scope tooltip visibility to the hovered index.
cy.get('[data-testid="InlineHelp"]').should('be.visible') asserts all tooltips without targeting the specific index, which can be flaky or mask a wrong tooltip. The method receives an index parameter and correctly targets the specific icon at that index, but the visibility assertion should match. Target the tooltip at the same index.

🔧 Suggested fix
  verifyTooltip(index) {
    cy.get('[data-testid="InlineHelp-icon"]').eq(index).trigger('mouseover');
-   cy.get('[data-testid="InlineHelp"]').should('be.visible');
+   cy.get('[data-testid="InlineHelp"]').eq(index).should('be.visible');
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
verifyTooltip(index) {
cy.get('[data-testid="InlineHelp-icon"]').eq(index).trigger('mouseover');
cy.get('[data-testid="InlineHelp"]').should('be.visible');
verifyTooltip(index) {
cy.get('[data-testid="InlineHelp-icon"]').eq(index).trigger('mouseover');
cy.get('[data-testid="InlineHelp"]').eq(index).should('be.visible');
}
🤖 Prompt for AI Agents
In `@cypress/pages/RoadmapPage.js` around lines 27 - 29, The verifyTooltip(index)
helper currently asserts visibility on all tooltips; update it to assert only
the tooltip corresponding to the hovered icon by selecting the same index for
the tooltip element (use the same index argument with the
'[data-testid="InlineHelp"]' selector, e.g., call .eq(index) before
.should('be.visible')). This ensures the hover assertion targets the specific
tooltip shown by the earlier
cy.get('[data-testid="InlineHelp-icon"]').eq(index).trigger('mouseover') call.

}
}

export default RoadmapPage;
8 changes: 6 additions & 2 deletions cypress/pages/homepage.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ class HomePage {
this.verifyElementIsVisible('[data-testid="Navbar-logo"]');
}

verifyHeader(text = headerText) {
this.verifyHeadingExists(text);
verifyHeader() {
this.verifyPageLoaded();
}

verifyPageLoaded() {
this.verifyHeadingExists(headerText);
}

verifyGithubStarButton(link = githubStarLink) {
Expand Down
5 changes: 5 additions & 0 deletions cypress/support/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function verifyLinks(linksArray, verifyFn, urlKey = 'url', labelKey = 'label') {
linksArray.forEach((link) => {
verifyFn(link[urlKey], link[labelKey]);
});
}