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
29 changes: 29 additions & 0 deletions .github/workflows/test.yml-template
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Test

on:
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- name: Upload HTML report(backstop data)
if: ${{ always() }}
uses: actions/upload-artifact@v2
with:
name: report
path: backstop_data
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Check font styles. Use [IBM Plex Sans](https://fonts.google.com/specimen/IBM+Ple
11. `git push origin develop` - to send you code for PR.
12. Create a Pull Request (PR) from your branch `develop` to branch `master` of original repo.
13. Replace `<your_account>` with your Github username in the
[DEMO LINK](https://<your_account>.github.io/Museum/).
[DEMO LINK](https://serezatkacik8-boop.github.io/Museum/).
14. Copy `DEMO LINK` to the PR description.

> To update you PR repeat steps 7-11.
11 changes: 11 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { defineConfig } = require("cypress");

module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
supportFile: false,
specPattern: "cypress/e2e/**/*.cy.{js,jsx,ts,tsx}",
},
});
79 changes: 79 additions & 0 deletions cypress/e2e/scroll.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
describe('Horizontal Scroll Check', () => {
const resolutions = [768, 800, 900, 1024, 1025, 1100, 1200, 1280, 1366, 1440, 1600, 1920];

resolutions.forEach((width) => {
it(`should not have horizontal scroll at width ${width}px`, () => {
// Set viewport
cy.viewport(width, 900);

// Visit local server
cy.visit('http://localhost:5174/');

// Wait a moment for layout to settle/render images
cy.wait(500);

// Check for overflow
cy.window().then((win) => {
const doc = win.document;
const html = doc.documentElement;
const body = doc.body;

// Temporarily remove overflow-x: hidden to get accurate scrollWidth
html.style.overflowX = 'visible';
body.style.overflowX = 'visible';

const windowWidth = win.innerWidth;
const htmlScrollWidth = html.scrollWidth;
const bodyScrollWidth = body.scrollWidth;

cy.log(`Viewport Width: ${windowWidth}px`);
cy.log(`HTML Scroll Width: ${htmlScrollWidth}px`);
cy.log(`Body Scroll Width: ${bodyScrollWidth}px`);

// Check if there is overflow
const hasOverflow = htmlScrollWidth > windowWidth || bodyScrollWidth > windowWidth;

if (hasOverflow) {
// Find which elements are overflowing
const overflowingElements = [];
const allElements = doc.querySelectorAll('*');

allElements.forEach((el) => {
const rect = el.getBoundingClientRect();
// If the element's right edge is further right than the window width,
// and it is not a fixed/absolute container that is supposed to be full screen
if (rect.right > windowWidth) {
// Get selector or class name
const className = el.className || '';
const id = el.id || '';
const tagName = el.tagName.toLowerCase();
const selector = `${tagName}${id ? '#' + id : ''}${className ? '.' + className.split(' ').join('.') : ''}`;

// Only log if it's a visible element that has layout size
if (rect.width > 0 && rect.height > 0) {
overflowingElements.push({
selector,
left: rect.left,
right: rect.right,
width: rect.width,
});
}
}
});

cy.log('Overflowing Elements:', JSON.stringify(overflowingElements, null, 2));

// Throw error so the test fails and lists the overflowing elements
const elementDetails = overflowingElements
.map((el) => `${el.selector} (left: ${el.left}px, right: ${el.right}px, width: ${el.width}px)`)
.join('\n');
throw new Error(`Horizontal scroll detected at ${width}px. Overflowing elements:\n${elementDetails}`);
}

// Assert no overflow
expect(htmlScrollWidth).to.be.at.most(windowWidth);
expect(bodyScrollWidth).to.be.at.most(windowWidth);
});
});
});
});
92 changes: 92 additions & 0 deletions cypress/e2e/scroll_behavior.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
describe('Scroll Functionality Tests', () => {
beforeEach(() => {
// Set desktop viewport
cy.viewport(1280, 900);
// Disable smooth scrolling and animations for instant, reliable assertions
cy.visit('http://localhost:5174/', {
onBeforeLoad(win) {
win.addEventListener('stylesLoaded', () => {
const style = win.document.createElement('style');
style.innerHTML = `
html, body {
scroll-behavior: auto !important;
}
* {
transition: none !important;
animation: none !important;
}
`;
win.document.head.appendChild(style);
});
}
});
});

it('should have vertical scroll on the main page', () => {
cy.window().then((win) => {
const doc = win.document;
const scrollHeight = doc.documentElement.scrollHeight;
const clientHeight = doc.documentElement.clientHeight;

cy.log(`Scroll Height: ${scrollHeight}px`);
cy.log(`Client Height: ${clientHeight}px`);

// Page must be scrollable vertically
expect(scrollHeight).to.be.greaterThan(clientHeight);
});
});

it('should scroll to sections when clicking header links', () => {
// On desktop, the drawer navigation works by checking the toggle #burger-toggle
cy.get('#burger-toggle').check({ force: true });

// Inject style to ensure scroll-behavior: auto is applied
cy.window().then((win) => {
const style = win.document.createElement('style');
style.innerHTML = 'html { scroll-behavior: auto !important; }';
win.document.head.appendChild(style);
});

// Click "Галерея" link
cy.get('a[href="#gallery"]').first().click({ force: true });
cy.wait(200);

// Verify window is scrolled down
cy.window().then((win) => {
expect(win.scrollY).to.be.greaterThan(100);
});

// Check gallery section is visible
cy.get('#gallery').then(($el) => {
const rect = $el[0].getBoundingClientRect();
expect(rect.top).to.be.closeTo(0, 10);
});
});

it('should scroll to top when clicking the scroll-to-top button', () => {
// Set viewport to tablet/mobile to test the button
cy.viewport(768, 900);

cy.window().then((win) => {
const style = win.document.createElement('style');
style.innerHTML = 'html { scroll-behavior: auto !important; }';
win.document.head.appendChild(style);
});

// Scroll to bottom
cy.scrollTo('bottom');
cy.wait(200);

cy.window().then((win) => {
expect(win.scrollY).to.be.greaterThan(500);
});

// Click the scroll-to-top button
cy.get('#scroll-top-btn').click({ force: true });
cy.wait(200);

cy.window().then((win) => {
expect(win.scrollY).to.be.closeTo(0, 5);
});
});
});
Loading
Loading