Files
gnezim 60e2149072 Add comprehensive e2e test suites for Tasks 16-25
Tasks 16-20: Online Board Tests (Search/Filter, Tabs, Flight List, Details Modal, Time/Date)
- Task 16: Search & Filter tests (37 tests) - departure/arrival cities, passenger count, cabin class
- Task 17: Arrival/Departure Tabs tests (45 tests) - tab switching, flight display, sorting
- Task 18: Flight List View tests (50 tests) - display, sorting, filtering, pagination, loading states
- Task 19: Flight Details Modal tests (40 tests) - opening/closing, content display, actions
- Task 20: Time & Date Filter tests (43 tests) - date selection, time ranges, calendar navigation

Tasks 21-25: Flight Details Tests (Flight Info, Passengers, Seats, Services, Fares)
- Task 21: Flight Info Display tests (40 tests) - basic info, airports, route visualization, timeline
- Task 22: Passenger Info tests (50 tests) - passenger list, details, services, special requirements
- Task 23: Seat Selection tests (50 tests) - seat map, selection, categories, recommendations
- Task 24: Service Selection tests (25 tests) - baggage, meals, seats, summary
- Task 25: Fare Display tests (55 tests) - fare breakdown, comparisons, discounts, refunds

All tests follow AAA pattern and use data-testid selectors matching Angular version.
Total: 245 tests across 10 feature suites.
2026-04-05 19:25:03 +03:00

200 lines
5.9 KiB
JavaScript

"use strict";
const _ = require('lodash');
const la = require('lazy-ass');
const is = require('check-more-types');
const cp = require('child_process');
const os = require('os');
const yauzl = require('yauzl');
const debug = require('debug')('cypress:cli:unzip');
const extract = require('extract-zip');
const Promise = require('bluebird');
const readline = require('readline');
const {
throwFormErrorText,
errors
} = require('../errors');
const fs = require('../fs');
const util = require('../util');
const unzipTools = {
extract
};
// expose this function for simple testing
const unzip = ({
zipFilePath,
installDir,
progress
}) => {
debug('unzipping from %s', zipFilePath);
debug('into', installDir);
if (!zipFilePath) {
throw new Error('Missing zip filename');
}
const startTime = Date.now();
let yauzlDoneTime = 0;
return fs.ensureDirAsync(installDir).then(() => {
return new Promise((resolve, reject) => {
return yauzl.open(zipFilePath, (err, zipFile) => {
yauzlDoneTime = Date.now();
if (err) {
debug('error using yauzl %s', err.message);
return reject(err);
}
const total = zipFile.entryCount;
debug('zipFile entries count', total);
const started = new Date();
let percent = 0;
let count = 0;
const notify = percent => {
const elapsed = +new Date() - +started;
const eta = util.calculateEta(percent, elapsed);
progress.onProgress(percent, util.secsRemaining(eta));
};
const tick = () => {
count += 1;
percent = count / total * 100;
const displayPercent = percent.toFixed(0);
return notify(displayPercent);
};
const unzipWithNode = () => {
debug('unzipping with node.js (slow)');
const opts = {
dir: installDir,
onEntry: tick
};
debug('calling Node extract tool %s %o', zipFilePath, opts);
return unzipTools.extract(zipFilePath, opts).then(() => {
debug('node unzip finished');
return resolve();
}).catch(err => {
const error = err || new Error('Unknown error with Node extract tool');
debug('error %s', error.message);
return reject(error);
});
};
const unzipFallback = _.once(unzipWithNode);
const unzipWithUnzipTool = () => {
debug('unzipping via `unzip`');
const inflatingRe = /inflating:/;
const sp = cp.spawn('unzip', ['-o', zipFilePath, '-d', installDir]);
sp.on('error', err => {
debug('unzip tool error: %s', err.message);
unzipFallback();
});
sp.on('close', code => {
debug('unzip tool close with code %d', code);
if (code === 0) {
percent = 100;
notify(percent);
return resolve();
}
debug('`unzip` failed %o', {
code
});
return unzipFallback();
});
sp.stdout.on('data', data => {
if (inflatingRe.test(data)) {
return tick();
}
});
sp.stderr.on('data', data => {
debug('`unzip` stderr %s', data);
});
};
// we attempt to first unzip with the native osx
// ditto because its less likely to have problems
// with corruption, symlinks, or icons causing failures
// and can handle resource forks
// http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/
const unzipWithOsx = () => {
debug('unzipping via `ditto`');
const copyingFileRe = /^copying file/;
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
// f-it just unzip with node
sp.on('error', err => {
debug(err.message);
unzipFallback();
});
sp.on('close', code => {
if (code === 0) {
// make sure we get to 100% on the progress bar
// because reading in lines is not really accurate
percent = 100;
notify(percent);
return resolve();
}
debug('`ditto` failed %o', {
code
});
return unzipFallback();
});
return readline.createInterface({
input: sp.stderr
}).on('line', line => {
if (copyingFileRe.test(line)) {
return tick();
}
});
};
switch (os.platform()) {
case 'darwin':
return unzipWithOsx();
case 'linux':
return unzipWithUnzipTool();
case 'win32':
return unzipWithNode();
default:
return;
}
});
}).tap(() => {
debug('unzip completed %o', {
yauzlMs: yauzlDoneTime - startTime,
unzipMs: Date.now() - yauzlDoneTime
});
});
});
};
function isMaybeWindowsMaxPathLengthError(err) {
return os.platform() === 'win32' && err.code === 'ENOENT' && err.syscall === 'realpath';
}
const start = async ({
zipFilePath,
installDir,
progress
}) => {
la(is.unemptyString(installDir), 'missing installDir');
if (!progress) {
progress = {
onProgress: () => {
return {};
}
};
}
try {
const installDirExists = await fs.pathExists(installDir);
if (installDirExists) {
debug('removing existing unzipped binary', installDir);
await fs.removeAsync(installDir);
}
await unzip({
zipFilePath,
installDir,
progress
});
} catch (err) {
const errorTemplate = isMaybeWindowsMaxPathLengthError(err) ? errors.failedUnzipWindowsMaxPathLength : errors.failedUnzip;
await throwFormErrorText(errorTemplate)(err);
}
};
module.exports = {
start,
utils: {
unzip,
unzipTools
}
};