diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml new file mode 100644 index 0000000..0c643ca --- /dev/null +++ b/.github/workflows/unit.yml @@ -0,0 +1,29 @@ +name: Run Unit Tests +on: + pull_request: + types: [opened, reopened, synchronize] + push: + branches: [master] + tags: ['*'] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + run-unit-tests: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + + - name: Use Node.js 22 + uses: actions/setup-node@v5 + with: + node-version: 22 + cache: 'npm' + + - run: npm ci + + - name: Run unit tests + run: npx vitest run diff --git a/cypress/e2e/eip7594.cy.ts b/cypress/e2e/eip7594.cy.ts index 2cb69b0..ce38f7d 100644 --- a/cypress/e2e/eip7594.cy.ts +++ b/cypress/e2e/eip7594.cy.ts @@ -13,7 +13,8 @@ describe('EIP-7594/PeerDAS Tests', () => { ) // Select different example - cy.get('#eip-7594-c').find('select').select(2) + cy.get('#eip-7594-c .e-select').click() + cy.get('#eip-7594-c [role="option"]').eq(1).click() cy.get('#eip-7594-c textarea', { timeout: 10000 }).should( 'contain.value', '00000000000000000000000000000000000000000', @@ -27,13 +28,9 @@ describe('EIP-7594/PeerDAS Tests', () => { .should('contain.text', text, { timeout: 25000 }) text = '0x8bd1e6e38b2b54735c6f0102022510cf2abc2e4c6c5a437cba9831662c9f112e61e2a6ced8ce63b3de18cb9cc99ae21e' - cy.get('#eip-7594-c .4844-box') - .find('p') - .should('contain.text', text, { timeout: 25000 }) + cy.get('#eip-7594-c .4844-box').find('p').should('contain.text', text, { timeout: 25000 }) text = '0x8d90ed38068f3561132d9264db8c8dfb5237af24a6e28c3d4e72d3ad8d51d97be5733ddc382c9718822cb29ccc26364e' - cy.get('#eip-7594-c .7594-box') - .find('p:first') - .should('contain.text', text, { timeout: 25000 }) + cy.get('#eip-7594-c .7594-box').find('p:first').should('contain.text', text, { timeout: 25000 }) }) }) diff --git a/cypress/e2e/eip7883_Precompile_R.cy.ts b/cypress/e2e/eip7883_Precompile_R.cy.ts index 89824bc..018616e 100644 --- a/cypress/e2e/eip7883_Precompile_R.cy.ts +++ b/cypress/e2e/eip7883_Precompile_R.cy.ts @@ -15,10 +15,7 @@ describe('EIP-7823/Precompile Component Tests', () => { cy.contains('h1', 'Feel Your Protocol') cy.contains('h3', 'ModExp') - cy.get('#eip-7883-c textarea', { timeout: 10000 }).should( - 'have.value', - bytesExpected, - ) + cy.get('#eip-7883-c textarea', { timeout: 10000 }).should('have.value', bytesExpected) cy.get('#eip-7883-c input').eq(0).should('have.value', '03') cy.get('#eip-7883-c input').eq(1).should('have.value', '03') cy.get('#eip-7883-c input').eq(2).should('have.value', '02') @@ -94,7 +91,8 @@ describe('EIP-7823/Precompile Component Tests', () => { cy.get('input').eq(2).should('have.value', '0202') // examples - cy.get('.examples-select').select('Simple') + cy.get('.e-select').click() + cy.contains('[role="option"]', 'Simple').click() cy.get('input').eq(0).should('have.value', '03') cy.get('input').eq(1).should('have.value', '03') cy.get('input').eq(2).should('have.value', '02') diff --git a/cypress/e2e/eip7951.cy.ts b/cypress/e2e/eip7951.cy.ts index 2a447ed..342baf7 100644 --- a/cypress/e2e/eip7951.cy.ts +++ b/cypress/e2e/eip7951.cy.ts @@ -17,9 +17,8 @@ describe('EIP-7951/secp256r1 Precompile Support', () => { cy.get('.post-hardfork').find('p').eq(0).should('include.text', '6900 Gas') // Select different example - cy.get('#eip-7951-c') - .find('select') - .select('Invalid (Wycheproof), r value too large') + cy.get('#eip-7951-c .e-select').click() + cy.contains('[role="option"]', 'Invalid (Wycheproof), r value too large').click() cy.get('#eip-7951-c textarea', { timeout: 10000 }).should( 'contain.value', '532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25', diff --git a/cypress/e2e/sites.cy.ts b/cypress/e2e/sites.cy.ts new file mode 100644 index 0000000..35d3e6b --- /dev/null +++ b/cypress/e2e/sites.cy.ts @@ -0,0 +1,55 @@ +describe('Home', () => { + it('loads and displays topics and explorations', () => { + cy.visit('/') + cy.contains('h2', 'Fusaka').should('be.visible') + cy.get('.exploration-c').should('have.length.gte', 1) + }) + + it('topic link navigates to topic page', () => { + cy.visit('/') + cy.contains('h2', 'Fusaka').closest('a').click() + cy.url().should('include', '/fusaka') + }) + + it('exploration card navigates to exploration page', () => { + cy.visit('/') + cy.get('.exploration-c').first().closest('a').click() + cy.url().should('match', /\/eip-\d+/) + }) +}) + +describe('Topic (Fusaka)', () => { + it('loads all exploration widgets', () => { + cy.visit('/fusaka') + cy.get('#eip-7883-c', { timeout: 10000 }).should('exist') + cy.get('#eip-7594-c', { timeout: 10000 }).should('exist') + cy.get('#eip-7951-c', { timeout: 10000 }).should('exist') + }) +}) + +describe('Imprint', () => { + it('loads and shows key sections', () => { + cy.visit('/imprint') + cy.contains('h3', 'CONTACT') + cy.contains('h3', 'ACKNOWLEDGEMENTS') + cy.contains('h3', 'DATA') + }) +}) + +describe('Navigation', () => { + it('full navigation flow through the site', () => { + cy.visit('/') + cy.get('header').contains('Feel Your Protocol') + cy.get('footer').contains('Imprint') + + cy.get('#exploration-navi').click() + cy.contains('[role="option"]', 'EIP-7883').click() + cy.url().should('include', '/eip-7883') + + cy.get('footer').contains('Imprint').click() + cy.url().should('include', '/imprint') + + cy.contains('h1', 'Feel Your Protocol').click() + cy.url().should('eq', Cypress.config().baseUrl + '/') + }) +}) diff --git a/cypress/e2e/sites/home.cy.ts b/cypress/e2e/sites/home.cy.ts deleted file mode 100644 index 8bcd0d1..0000000 --- a/cypress/e2e/sites/home.cy.ts +++ /dev/null @@ -1,22 +0,0 @@ -describe('Home Page', () => { - beforeEach(() => { - cy.visit('/') - }) - - it('renders intro and project overview', () => { - cy.contains('Interactive Ethereum Protocol Explorations') - cy.contains('About the Project') - cy.contains('Feel Your Protocol is a collaborative open-source project') - }) - - it('renders topic box with dancer', () => { - cy.contains('h2', 'Fusaka') - cy.get('img').should('exist') - }) - - it('featured exploration boxes have entries and links work', () => { - cy.get('.exploration-c').should('have.length.gte', 1) - cy.get('.exploration-c').first().parents('a').click() - cy.url().should('include', '/eip-') - }) -}) diff --git a/cypress/e2e/sites/imprint.cy.ts b/cypress/e2e/sites/imprint.cy.ts deleted file mode 100644 index 0b9cbf0..0000000 --- a/cypress/e2e/sites/imprint.cy.ts +++ /dev/null @@ -1,22 +0,0 @@ -describe('Imprint Page', () => { - beforeEach(() => { - cy.visit('/imprint') - }) - - it('renders contact section', () => { - cy.contains('h3', 'CONTACT') - cy.contains('Holger Drewes') - }) - - it('renders acknowledgements', () => { - cy.contains('h3', 'ACKNOWLEDGEMENTS') - cy.contains('li', 'EthereumJS') - cy.contains('li', 'Midjourney') - cy.contains('li', 'Tailwind') - }) - - it('renders data privacy section', () => { - cy.contains('h3', 'DATA') - cy.contains('does not collect any personal data') - }) -}) diff --git a/cypress/e2e/sites/structure.cy.ts b/cypress/e2e/sites/structure.cy.ts deleted file mode 100644 index fc90d74..0000000 --- a/cypress/e2e/sites/structure.cy.ts +++ /dev/null @@ -1,45 +0,0 @@ -describe('Site Structure', () => { - it('header renders on every page', () => { - for (const path of ['/', '/fusaka', '/eip-7883-modexp-gas-cost-increase', '/imprint']) { - cy.visit(path) - cy.get('header').within(() => { - cy.contains('h1', 'Feel Your Protocol') - cy.get('nav').should('exist') - }) - } - }) - - it('footer renders on every page', () => { - for (const path of ['/', '/fusaka', '/eip-7883-modexp-gas-cost-increase', '/imprint']) { - cy.visit(path) - cy.get('footer').within(() => { - cy.contains('a', 'Imprint') - cy.contains('a', 'GitHub') - }) - } - }) - - it('navigation links work', () => { - cy.visit('/') - - cy.contains('h2', 'Fusaka').click() - cy.url().should('include', '/fusaka') - - cy.get('#exploration-navi').select('EIP-7883') - cy.url().should('include', '/eip-7883') - - cy.get('footer').contains('Imprint').click() - cy.url().should('include', '/imprint') - - cy.contains('h1', 'Feel Your Protocol').click() - cy.url().should('eq', Cypress.config().baseUrl + '/') - }) - - it('exploration dropdown lists all explorations', () => { - cy.visit('/') - cy.get('#exploration-navi option').should('have.length.gte', 4) - cy.get('#exploration-navi').contains('EIP-7594') - cy.get('#exploration-navi').contains('EIP-7883') - cy.get('#exploration-navi').contains('EIP-7951') - }) -}) diff --git a/cypress/e2e/sites/topic.cy.ts b/cypress/e2e/sites/topic.cy.ts deleted file mode 100644 index 1cd02ef..0000000 --- a/cypress/e2e/sites/topic.cy.ts +++ /dev/null @@ -1,35 +0,0 @@ -describe('Topic Page (Fusaka)', () => { - beforeEach(() => { - cy.visit('/fusaka') - }) - - it('renders topic title and external link', () => { - cy.contains('Fusaka') - cy.get('a[href="https://forkcast.org/upgrade/fusaka"]').should('exist') - }) - - it('displays all topic EIP widgets', () => { - cy.get('#eip-7883-c', { timeout: 10000 }).should('exist') - cy.get('#eip-7594-c', { timeout: 10000 }).should('exist') - cy.get('#eip-7951-c', { timeout: 10000 }).should('exist') - }) - - it('EIP widgets show titles', () => { - cy.get('#eip-7883-c').contains('h3', 'ModExp') - cy.get('#eip-7951-c').contains('h3', 'secp256r1') - cy.get('#eip-7594-c').contains('h3', 'Peer Data') - }) - - it('EIP widgets have EIP links', () => { - cy.get('#eip-7883-c .visit-exploration-button') - .should('have.attr', 'href') - .and('include', 'eip-7883') - cy.get('#eip-7951-c .visit-exploration-button') - .should('have.attr', 'href') - .and('include', 'eip-7951') - }) - - it('renders dancer image', () => { - cy.get('img').should('exist') - }) -}) diff --git a/dist/docs/404.html b/dist/docs/404.html index 668e0d9..5083a72 100644 --- a/dist/docs/404.html +++ b/dist/docs/404.html @@ -9,14 +9,14 @@ - +
- +