diff --git a/.gitignore b/.gitignore index 4a2ff1a8a09d..8a6940cc8107 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules out config/posts.json config/case-studies.json +config/adopters.json public/rss.xml .env.local yarn.lock diff --git a/config/adopters.yml b/config/adopters.yml new file mode 100644 index 000000000000..5dae9fb1c946 --- /dev/null +++ b/config/adopters.yml @@ -0,0 +1,47 @@ +- companyName: Reiffeisen Bank + useCase: Continuous Integration and Continuous Delivery (CI/CD) pipeline based on GitOps to deploy a topology built on Async API definitions using a Kubernetes operator to an Apache Pulsar cluster. + resources: + - title: Video - From an AsyncAPI Definition to a Deployed Pulsar Topology Via GitOps + link: https://www.youtube.com/watch?v=_MwzLZMwFN8 + +- companyName: LEGO Group + useCase: Broker management, where developers do not access the management console themselves, but rely on uploading AsyncAPI documents to a self service API that provisions access and topics specified in documents. + resources: + - title: Video - Documentation as Configuration for Management of Apache Pulsar + link: https://www.youtube.com/watch?v=m8I0fYjx6Cc + +- companyName: LEGO Group + useCase: Define, document and distribute event-driven APIs. Ensuring consistency and governance + resources: + - title: Video - Cross-Domain Events with AsyncAPI and AWS + link: https://www.youtube.com/watch?v=qjarcJQVLOg + +- companyName: Bank of New Zealand + useCase: Decentralized company-wide governance strategy for API. A self service for publishing APIs and docs. + resources: + - title: "Video - Self-service Events & Decentralised Governance with AsyncAPI: A Real World Example" + link: https://www.confluent.io/events/kafka-summit-apac-2021/self-service-events-and-decentralised-governance-with-asyncapi-a-real-world/ + +- companyName: Zora Robotics + useCase: Documenting lot products public MQTT API and building a developers portal. + resources: + - title: Video - Buliding and managing an extensive API for Robotics and loT + link: https://www.youtube.com/watch?v=yjHgT0n2BtA + - title: Docs - Buliding and managing an extensive API for Robotics and loT + link: https://docs.zorabots.be/dev-mqtt-docs/latest/index.html + +- companyName: Walmart + useCase: Managing a central API Hub for internal teams. Using AsyncAPI for events discoverability an visibility in a single place. AsyncAPI also enabled company-wide governance on asynchronous APIs. + resources: + - title: Video - Time For AsyncAPI Specification + link: https://www.youtube.com/watch?v=SxTpGRaNIPo + +- companyName: eBay + useCase: Enabling partners to build with eBay through asynchronous communication. Public AsyncAPI documents enable code generation and faster integration. It also enables governance and standardisation. + resources: + - title: "Video - AsyncAPI 2.0: Enabling the Event-Driven World" + link: https://www.youtube.com/watch?v=SxTpGRaNIPo + - title: "Article - AsyncAPI 2.0: Enabling the Event-Driven World" + link: https://innovation.ebayinc.com/tech/engineering/asyncapi-2-0-enabling-the-event-driven-world/ + - title: Docs - Overview of Notification API with public AsyncAPI documents + link: https://developer.ebay.com/api-docs/commerce/notification/overview.html \ No newline at end of file diff --git a/cypress/test/components/CaseStudyCard.cy.js b/cypress/test/components/CaseStudyCard.cy.js index 2e14e4b176f0..7fc273f8bc3a 100644 --- a/cypress/test/components/CaseStudyCard.cy.js +++ b/cypress/test/components/CaseStudyCard.cy.js @@ -1,7 +1,10 @@ import React from 'react'; import { mount } from 'cypress/react'; import CaseStudyCard from '../../../components/CaseStudyCard'; -import CaseStudiesList from "../../../config/case-studies.json"; +import CaseStudiesList from '../../../config/case-studies.json'; +import AdoptersList from '../../../config/adopters.json'; +import Casestudies from '../../../pages/casestudies'; + describe('CaseStudyCard Component', () => { it('renders the CaseStudyCard component with study data', () => { diff --git a/cypress/test/pages/casestudies/index.cy.js b/cypress/test/pages/casestudies/index.cy.js index e8907f6baad2..282ae639e059 100644 --- a/cypress/test/pages/casestudies/index.cy.js +++ b/cypress/test/pages/casestudies/index.cy.js @@ -1,6 +1,8 @@ import Casestudies from "../../../../pages/casestudies"; import MockApp from "../../../utils/MockApp"; -import {mount} from 'cypress/react'; +import { mount } from 'cypress/react'; +import AdoptersList from "../../../../config/adopters.json" + describe('Test for Case Study Pages', () => { it('renders correctly', () => { mount( @@ -8,7 +10,32 @@ describe('Test for Case Study Pages', () => { ); - cy.get('[data-testid="CaseStudy-main"]').should('exist'); - cy.get('[data-testid="CaseStudy-card"]').should('exist'); + cy.get('[data-testid="CaseStudy-main"]').should('exist'); + cy.get('[data-testid="CaseStudy-card"]').should('exist'); }); + + it('Adopters section renders correctly', () => { + mount( + + + + ); + cy.get('[data-testid="Adopters"]').should('have.length', AdoptersList.length); + + cy.get('table') + .should('exist') + .within(() => { + // Check table headers + cy.get('th').eq(0).should('have.text', 'Company name'); + cy.get('th').eq(1).should('have.text', 'Use Case'); + cy.get('th').eq(2).should('have.text', 'Resources'); + + // Check table data + cy.get('tbody tr').should('have.length', AdoptersList.length); + AdoptersList.forEach((entry, index) => { + cy.get('tbody tr').eq(index).find('td').eq(0).should('have.text', entry.companyName); + cy.get('tbody tr').eq(index).find('td').eq(1).should('have.text', entry.useCase); + }); + }); + }) }); \ No newline at end of file diff --git a/pages/casestudies/index.js b/pages/casestudies/index.js index a4f30e5995ce..40fa02c1d699 100644 --- a/pages/casestudies/index.js +++ b/pages/casestudies/index.js @@ -4,6 +4,7 @@ import Paragraph from '../../components/typography/Paragraph'; import TextLink from '../../components/typography/TextLink'; import Heading from "../../components/typography/Heading"; import CaseStudiesList from "../../config/case-studies.json"; +import AdoptersList from "../../config/adopters.json" export default function Casestudies() { const description = @@ -41,7 +42,61 @@ export default function Casestudies() { + +
+
+
+ + Adopters + + + Check out how different companies use AsyncAPI and what problems they solve. + + + Feel free to submit a pull request with information about how your company uses AsyncAPI. We know that + writing an official case study might be time consuming and requires too much internal paper work. + Let's make sure we can at least capture a use case that is already a great learning information for the + community. + +
+
+
+ +
+
+ + + + + + + + + + {AdoptersList.map((entry, index) => ( + + + + + + ))} + +
Company nameUse CaseResources
{entry.companyName}{entry.useCase} + +
+
+
); } + + diff --git a/scripts/adopters/index.js b/scripts/adopters/index.js new file mode 100644 index 000000000000..0f5eeb427cf5 --- /dev/null +++ b/scripts/adopters/index.js @@ -0,0 +1,18 @@ +const { promises: { readFile, writeFile } } = require('fs'); +const { convertToJson } = require('../utils'); +const { resolve } = require('path'); + +module.exports = async function buildAdoptersList() { + try { + const AdoptersContent = await readFile('config/adopters.yml', 'utf-8'); + const jsonContent = convertToJson(AdoptersContent); + + await writeFile( + resolve(__dirname, '../../config', 'adopters.json'), + JSON.stringify(jsonContent) + ); + } catch (err) { + console.error(err); + throw err; + } +}; diff --git a/scripts/index.js b/scripts/index.js index 835ccd7b6edf..f6e462c35d4f 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -1,6 +1,7 @@ const rssFeed = require('./build-rss'); const buildPostList = require('./build-post-list'); const buildCaseStudiesList = require('./casestudies'); +const buildAdoptersList = require('./adopters') const buildFinanceInfoList = require('./finance') async function start() { @@ -18,6 +19,7 @@ async function start() { 'jobs/rss.xml' ); await buildCaseStudiesList(); + await buildAdoptersList(); await buildFinanceInfoList(); }