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

190 lines
4.1 KiB
JavaScript

"use strict";
let util = require("util");
let Stream = require("stream");
let ChunkStream = (module.exports = function () {
Stream.call(this);
this._buffers = [];
this._buffered = 0;
this._reads = [];
this._paused = false;
this._encoding = "utf8";
this.writable = true;
});
util.inherits(ChunkStream, Stream);
ChunkStream.prototype.read = function (length, callback) {
this._reads.push({
length: Math.abs(length), // if length < 0 then at most this length
allowLess: length < 0,
func: callback,
});
process.nextTick(
function () {
this._process();
// its paused and there is not enought data then ask for more
if (this._paused && this._reads && this._reads.length > 0) {
this._paused = false;
this.emit("drain");
}
}.bind(this)
);
};
ChunkStream.prototype.write = function (data, encoding) {
if (!this.writable) {
this.emit("error", new Error("Stream not writable"));
return false;
}
let dataBuffer;
if (Buffer.isBuffer(data)) {
dataBuffer = data;
} else {
dataBuffer = Buffer.from(data, encoding || this._encoding);
}
this._buffers.push(dataBuffer);
this._buffered += dataBuffer.length;
this._process();
// ok if there are no more read requests
if (this._reads && this._reads.length === 0) {
this._paused = true;
}
return this.writable && !this._paused;
};
ChunkStream.prototype.end = function (data, encoding) {
if (data) {
this.write(data, encoding);
}
this.writable = false;
// already destroyed
if (!this._buffers) {
return;
}
// enqueue or handle end
if (this._buffers.length === 0) {
this._end();
} else {
this._buffers.push(null);
this._process();
}
};
ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
ChunkStream.prototype._end = function () {
if (this._reads.length > 0) {
this.emit("error", new Error("Unexpected end of input"));
}
this.destroy();
};
ChunkStream.prototype.destroy = function () {
if (!this._buffers) {
return;
}
this.writable = false;
this._reads = null;
this._buffers = null;
this.emit("close");
};
ChunkStream.prototype._processReadAllowingLess = function (read) {
// ok there is any data so that we can satisfy this request
this._reads.shift(); // == read
// first we need to peek into first buffer
let smallerBuf = this._buffers[0];
// ok there is more data than we need
if (smallerBuf.length > read.length) {
this._buffered -= read.length;
this._buffers[0] = smallerBuf.slice(read.length);
read.func.call(this, smallerBuf.slice(0, read.length));
} else {
// ok this is less than maximum length so use it all
this._buffered -= smallerBuf.length;
this._buffers.shift(); // == smallerBuf
read.func.call(this, smallerBuf);
}
};
ChunkStream.prototype._processRead = function (read) {
this._reads.shift(); // == read
let pos = 0;
let count = 0;
let data = Buffer.alloc(read.length);
// create buffer for all data
while (pos < read.length) {
let buf = this._buffers[count++];
let len = Math.min(buf.length, read.length - pos);
buf.copy(data, pos, 0, len);
pos += len;
// last buffer wasn't used all so just slice it and leave
if (len !== buf.length) {
this._buffers[--count] = buf.slice(len);
}
}
// remove all used buffers
if (count > 0) {
this._buffers.splice(0, count);
}
this._buffered -= read.length;
read.func.call(this, data);
};
ChunkStream.prototype._process = function () {
try {
// as long as there is any data and read requests
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
let read = this._reads[0];
// read any data (but no more than length)
if (read.allowLess) {
this._processReadAllowingLess(read);
} else if (this._buffered >= read.length) {
// ok we can meet some expectations
this._processRead(read);
} else {
// not enought data to satisfy first request in queue
// so we need to wait for more
break;
}
}
if (this._buffers && !this.writable) {
this._end();
}
} catch (ex) {
this.emit("error", ex);
}
};