Files
flights_web/ClientApp/cypress/integration/features/responsive.cy.ts

403 lines
17 KiB
TypeScript

import * as moment from 'moment';
describe('Responsive Design & Mobile Tests', () => {
const today = moment().format('DD.MM.YYYY');
const testCity = 'Анапа';
const testCityCode = 'AAQ';
// Helper to check no horizontal scrolling
const checkNoHorizontalScroll = () => {
cy.get('body').then(($body) => {
const windowWidth = $body[0].ownerDocument.defaultView.innerWidth;
const scrollWidth = $body[0].scrollWidth;
expect(scrollWidth).to.equal(windowWidth);
});
};
// Helper to check touch target size (minimum 44x44px)
const checkTouchTargetSize = (selector: string) => {
cy.get(selector).should(($el) => {
const rect = $el[0].getBoundingClientRect();
expect(rect.width).to.be.at.least(44);
expect(rect.height).to.be.at.least(44);
});
};
// Helper to check element is not hidden
const checkElementVisible = (selector: string) => {
cy.get(selector).should('be.visible').should('not.have.css', 'overflow', 'hidden');
};
// Mobile Viewport Tests (375x667 - iPhone SE)
describe('Mobile Viewport (375x667 - iPhone SE)', () => {
beforeEach(() => {
cy.viewport('iphone-se2');
cy.intercept('GET', '**api/flights/v1.1/ru/board**').as('getFlights');
cy.forbidGeolocation();
cy.visit('/');
});
it('Mobile: Text is readable and not overflowing in filter section', () => {
cy.getByTestId('filter-section').should('be.visible');
cy.getByTestId('filter-section').then(($section) => {
const text = $section.text();
expect(text.length).to.be.greaterThan(0);
expect($section[0].scrollWidth).to.equal($section[0].clientWidth);
});
});
it('Mobile: Search button has minimum touch target size (44x44px)', () => {
checkTouchTargetSize('[data-testid="arrival-search-button"]');
});
it('Mobile: City input field has proper touch target size', () => {
checkTouchTargetSize('[data-testid="city-autocomplete-input"]');
});
it('Mobile: Calendar input has sufficient touch target size', () => {
checkTouchTargetSize('[data-testid="calendar-input"]');
});
it('Mobile: No horizontal scrolling on page load', () => {
checkNoHorizontalScroll();
});
it('Mobile: No horizontal scrolling after opening accordion', () => {
cy.getByTestId('accordion').should('exist').click();
checkNoHorizontalScroll();
});
it('Mobile: Form inputs are not hidden behind keyboard simulation', () => {
cy.getByTestId('city-autocomplete-input').should('be.visible').should('not.have.css', 'display', 'none');
cy.getByTestId('calendar-input').should('be.visible').should('not.have.css', 'display', 'none');
});
it('Mobile: Filter labels are readable and properly spaced', () => {
cy.getByTestId('filter-label').should('be.visible').each(($el) => {
const fontSize = window.getComputedStyle($el[0]).fontSize;
expect(parseInt(fontSize)).to.be.at.least(14);
});
});
it('Mobile: Input fields have adequate padding for mobile interaction', () => {
cy.getByTestId('city-autocomplete-input').should(($el) => {
const padding = window.getComputedStyle($el[0]).padding;
expect(padding).to.not.equal('0px');
});
});
it('Mobile: Hamburger menu opens and closes correctly', () => {
cy.getByTestId('hamburger-menu').should('exist').click();
cy.getByTestId('mobile-nav').should('be.visible');
cy.getByTestId('hamburger-menu').click();
cy.getByTestId('mobile-nav').should('not.be.visible');
});
it('Mobile: Accordion sections collapse and expand on tap', () => {
cy.getByTestId('accordion').should('exist');
cy.getByTestId('accordion').click();
cy.getByTestId('accordion-content').should('be.visible');
cy.getByTestId('accordion').click();
cy.getByTestId('accordion-content').should('not.be.visible');
});
it('Mobile: Images scale correctly without distortion', () => {
cy.getByTestId('company-logo').should('be.visible').each(($img) => {
const width = $img[0].getBoundingClientRect().width;
const height = $img[0].getBoundingClientRect().height;
expect(width).to.be.greaterThan(0);
expect(height).to.be.greaterThan(0);
});
});
it('Mobile: Button text is visible and not cut off', () => {
cy.getByTestId('arrival-search-button').should('be.visible').should(($btn) => {
const text = $btn.text();
expect(text).to.have.length.greaterThan(0);
});
});
it('Mobile: No text overflow in flight results', () => {
cy.getByTestId('city-autocomplete-input').type(testCity);
cy.getByTestId('calendar-input').type(today).type('{enter}');
cy.getByTestId('arrival-search-button').click();
cy.wait('@getFlights').then(() => {
cy.getByTestId('flight-result').first().then(($result) => {
expect($result[0].scrollWidth).to.equal($result[0].clientWidth);
});
});
});
it('Mobile: Touch targets for flight results are appropriately sized', () => {
cy.getByTestId('city-autocomplete-input').type(testCity);
cy.getByTestId('calendar-input').type(today).type('{enter}');
cy.getByTestId('arrival-search-button').click();
cy.wait('@getFlights').then(() => {
checkTouchTargetSize('[data-testid="flight-result"]');
});
});
it('Mobile: Proper spacing between interactive elements', () => {
cy.getByTestId('filter-section').should(($section) => {
const buttons = $section.find('[data-testid="arrival-search-button"]');
expect(buttons.length).to.be.greaterThan(0);
});
});
});
// Tablet Viewport Tests (768x1024 - iPad 2)
describe('Tablet Viewport (768x1024 - iPad 2)', () => {
beforeEach(() => {
cy.viewport('ipad-2');
cy.intercept('GET', '**api/flights/v1.1/ru/board**').as('getFlights');
cy.forbidGeolocation();
cy.visit('/');
});
it('Tablet: Layout is optimized and not stretched', () => {
cy.getByTestId('main-content').should('be.visible').then(($content) => {
const width = $content[0].getBoundingClientRect().width;
expect(width).to.be.lessThan(768);
expect(width).to.be.greaterThan(400);
});
});
it('Tablet: Layout is not too narrow', () => {
cy.getByTestId('filter-section').should('be.visible').then(($section) => {
const width = $section[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(500);
});
});
it('Tablet: Multi-column layout works correctly', () => {
cy.getByTestId('filter-row').should('be.visible');
cy.getByTestId('filter-row').then(($row) => {
const columns = $row.find('[data-testid*="filter-col"]');
expect(columns.length).to.be.greaterThan(0);
});
});
it('Tablet: Touch interactions work for tapping elements', () => {
cy.getByTestId('accordion').should('exist').trigger('touchstart').trigger('touchend');
cy.getByTestId('accordion-content').should('be.visible');
});
it('Tablet: Buttons are appropriately sized for tablet interaction', () => {
checkTouchTargetSize('[data-testid="arrival-search-button"]');
});
it('Tablet: Spacing between form elements is balanced', () => {
cy.getByTestId('filter-section').should(($section) => {
const marginBottom = window.getComputedStyle($section[0]).marginBottom;
expect(marginBottom).to.not.equal('0px');
});
});
it('Tablet: No layout breaking on tablet orientation', () => {
checkNoHorizontalScroll();
});
it('Tablet: Forms fit properly within viewport', () => {
cy.getByTestId('filter-section').should('be.visible').then(($form) => {
const viewportWidth = window.innerWidth;
const formWidth = $form[0].getBoundingClientRect().width;
expect(formWidth).to.be.lessThan(viewportWidth);
});
});
it('Tablet: Input fields display correctly with proper size', () => {
cy.getByTestId('city-autocomplete-input').should('be.visible').then(($input) => {
const height = $input[0].getBoundingClientRect().height;
expect(height).to.be.greaterThan(30);
});
});
it('Tablet: Swipe left gesture works on content', () => {
cy.getByTestId('main-content').swipeLeft();
});
it('Tablet: Swipe right gesture works on content', () => {
cy.getByTestId('main-content').swipeRight();
});
it('Tablet: No horizontal scrolling with all content visible', () => {
checkNoHorizontalScroll();
});
it('Tablet: Images scale appropriately for tablet display', () => {
cy.getByTestId('company-logo').should('be.visible').each(($img) => {
const width = $img[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(20);
expect(width).to.be.lessThan(150);
});
});
});
// Desktop Viewport Tests (1920x1080)
describe('Desktop Viewport (1920x1080)', () => {
beforeEach(() => {
cy.viewport(1920, 1080);
cy.intercept('GET', '**api/flights/v1.1/ru/board**').as('getFlights');
cy.forbidGeolocation();
cy.visit('/');
});
it('Desktop: Layout scales correctly without overflow', () => {
cy.getByTestId('main-content').should('be.visible').then(($content) => {
expect($content[0].scrollWidth).to.equal($content[0].clientWidth);
});
});
it('Desktop: No horizontal scrolling on large viewport', () => {
checkNoHorizontalScroll();
});
it('Desktop: All content is accessible without zooming', () => {
cy.getByTestId('filter-section').should('be.visible');
cy.getByTestId('city-autocomplete-input').should('be.visible');
cy.getByTestId('calendar-input').should('be.visible');
cy.getByTestId('arrival-search-button').should('be.visible');
});
it('Desktop: Multi-column layout is fully utilized', () => {
cy.getByTestId('filter-row').should('be.visible').then(($row) => {
const width = $row[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(1000);
});
});
it('Desktop: Typography is appropriate for large screens', () => {
cy.getByTestId('filter-section').should(($section) => {
const fontSize = window.getComputedStyle($section[0]).fontSize;
expect(parseInt(fontSize)).to.be.at.least(14);
});
});
it('Desktop: Buttons are properly proportioned for large screen', () => {
cy.getByTestId('arrival-search-button').should('be.visible').then(($btn) => {
const width = $btn[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(80);
});
});
it('Desktop: Form elements are well-spaced on large viewport', () => {
cy.getByTestId('filter-section').should(($section) => {
const padding = window.getComputedStyle($section[0]).padding;
expect(padding).to.not.equal('0px');
});
});
it('Desktop: Hover effects are available on buttons', () => {
cy.getByTestId('arrival-search-button').should('be.visible');
// Hover effect test - verify element responds to hover state
cy.getByTestId('arrival-search-button').trigger('mouseenter');
});
it('Desktop: Accordion content displays correctly on large screen', () => {
cy.getByTestId('accordion').should('exist').click();
cy.getByTestId('accordion-content').should('be.visible').then(($content) => {
const width = $content[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(200);
});
});
it('Desktop: Images are properly scaled for desktop display', () => {
cy.getByTestId('company-logo').should('be.visible').each(($img) => {
const width = $img[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(40);
});
});
it('Desktop: Page layout remains optimal with full-width utilization', () => {
cy.viewport(1920, 1080);
cy.get('body').then(($body) => {
const viewportWidth = window.innerWidth;
expect(viewportWidth).to.equal(1920);
});
});
it('Desktop: All form inputs are visible and accessible', () => {
cy.getByTestId('filter-section').find('[data-testid="city-autocomplete-input"]').should('be.visible');
cy.getByTestId('filter-section').find('[data-testid="calendar-input"]').should('be.visible');
});
it('Desktop: Navigation elements are properly sized for mouse interaction', () => {
cy.getByTestId('hamburger-menu').should('exist').then(($menu) => {
const width = $menu[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(30);
});
});
it('Desktop: Content does not extend beyond safe viewport margins', () => {
cy.get('body').then(($body) => {
const bodyWidth = $body[0].getBoundingClientRect().width;
const viewportWidth = window.innerWidth;
expect(bodyWidth).to.be.lessThanOrEqual(viewportWidth);
});
});
it('Desktop: Text remains readable across large viewport', () => {
cy.getByTestId('filter-label').should('be.visible').each(($el) => {
const lineHeight = window.getComputedStyle($el[0]).lineHeight;
const fontSize = window.getComputedStyle($el[0]).fontSize;
expect(parseInt(lineHeight)).to.be.greaterThan(parseInt(fontSize));
});
});
it('Desktop: Flight search results display correctly on large viewport', () => {
cy.getByTestId('city-autocomplete-input').type(testCity);
cy.getByTestId('calendar-input').type(today).type('{enter}');
cy.getByTestId('arrival-search-button').click();
cy.wait('@getFlights').then(() => {
cy.getByTestId('board-search-result').should('be.visible');
cy.getByTestId('flight-result').should('have.length.at.least', 1);
cy.getByTestId('flight-result').first().then(($result) => {
const width = $result[0].getBoundingClientRect().width;
expect(width).to.be.greaterThan(300);
});
});
});
});
// Cross-viewport Tests
describe('Cross-Viewport Responsive Tests', () => {
beforeEach(() => {
cy.intercept('GET', '**api/flights/v1.1/ru/board**').as('getFlights');
cy.forbidGeolocation();
});
it('Responsive: Search works consistently on mobile viewport', () => {
cy.viewport('iphone-se2');
cy.visit('/');
cy.getByTestId('city-autocomplete-input').type(testCity);
cy.getByTestId('calendar-input').type(today).type('{enter}');
cy.getByTestId('arrival-search-button').click();
cy.wait('@getFlights').then(() => {
cy.getByTestId('flight-result').should('have.length.at.least', 1);
});
});
it('Responsive: Search works consistently on tablet viewport', () => {
cy.viewport('ipad-2');
cy.visit('/');
cy.getByTestId('city-autocomplete-input').type(testCity);
cy.getByTestId('calendar-input').type(today).type('{enter}');
cy.getByTestId('arrival-search-button').click();
cy.wait('@getFlights').then(() => {
cy.getByTestId('flight-result').should('have.length.at.least', 1);
});
});
it('Responsive: Search works consistently on desktop viewport', () => {
cy.viewport(1920, 1080);
cy.visit('/');
cy.getByTestId('city-autocomplete-input').type(testCity);
cy.getByTestId('calendar-input').type(today).type('{enter}');
cy.getByTestId('arrival-search-button').click();
cy.wait('@getFlights').then(() => {
cy.getByTestId('flight-result').should('have.length.at.least', 1);
});
});
});
});