403 lines
17 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|
|
});
|