Files
enterprise-addons/stock_barcode/static/tests/tours/tour_helper_stock_barcode.js
T

425 lines
16 KiB
JavaScript

import { assert, fail } from "@stock/../tests/tours/tour_helper";
export { assert, fail };
/**
* Returns the line for the given index and ensure the line is an HTMLElement (fails otherwise).
*
* @param {(HTMLElement|integer)} lineOrIndex either the line itself, either the index to find it
* @param {string} errorClue
* @returns {HTMLElement}
*/
export function _getLineOrFail(lineOrIndex, errorClue = "No line found") {
const line =
typeof lineOrIndex === "number"
? document.querySelectorAll(".o_barcode_line")[lineOrIndex]
: lineOrIndex;
if (line instanceof HTMLElement) {
return line;
}
const errorMessage =
typeof lineOrIndex === "number"
? `${errorClue}: the given index (${lineOrIndex}) doesn't match an existing line`
: `${errorClue}: the given object isn't a line`;
fail(errorMessage);
}
/**
* @param {string} selector
* @param {Object} description
* @param {string} [description.barcode] the line's product's barcode
* @param {Boolean} [description.completed] get only completed line if true
* @param {Boolean} [description.selected] get only selected line if true
* @param {string} [description.selector]
* @returns {string}
*/
export function _prepareSelector(selector, description) {
const { barcode, selected, completed } = description;
const dataPackage = description.package;
if (selected !== undefined) {
selector += selected ? ".o_selected" : ":not(.o_selected)";
}
if (completed !== undefined) {
selector += completed ? ".o_line_completed" : ":not(.o_line_completed)";
}
selector += barcode ? `[data-barcode="${barcode}"]` : "";
selector += dataPackage ? `[data-package="${dataPackage}"]` : "";
description.selector = selector;
return selector;
}
/**
* Get and returns exactly one line, fails if multiple lines are found).
* @param {Object} description @see getLines
* @returns {HTMLElement}
*/
export function getLine(description = {}) {
const line = getLines(description);
if (line.length > 1) {
fail(
`getLine: Multiple lines were found for the selector "${description.selector}" (use 'getLines' instead if its wanted)`
);
} else if (line.length === 0) {
fail(`getLine: No line was found for the selector "${description.selector}"`);
}
return line[0];
}
/**
* Get and returns all lines matching the given description, fails if no line is found.
* @param {Object} [description] if no description, will return all the barcode's line
* @see _prepareSelector for more information about description's keys.
* @returns {Element[]}
*/
export function getLines(description = {}) {
const selector = _prepareSelector(":not(.o_sublines) > .o_barcode_line", description);
const lines = document.querySelectorAll(selector);
const { index } = description;
if (index !== undefined) {
if (typeof index === "number") {
// Single index (not an array), returns only one line.
return [lines[index]];
}
const chosenLines = [];
for (const i of index) {
chosenLines.push(lines[i]);
}
if (chosenLines.length !== index.length) {
fail(`Expects ${index.length} lines, got ${chosenLines.length}`);
}
return chosenLines;
}
return Array.from(lines);
}
export function getSubline(description = {}) {
const subline = getSublines(description);
if (subline.length > 1) {
fail(`Multiple sublines were found for the selector "${description.selector}"`);
}
return subline[0];
}
export function getSublines(description = {}) {
const selector = _prepareSelector(".o_sublines .o_barcode_line", description);
const sublines = document.querySelectorAll(selector);
if (!sublines.length) {
fail(`No subline was found for the selector "${selector}"`);
}
return sublines;
}
export function triggerKeydown(eventKey, shiftkey = false) {
const params = { bubbles: true, key: eventKey, shiftKey: shiftkey };
document
.querySelector(".o_barcode_client_action")
.dispatchEvent(new window.KeyboardEvent("keydown", params));
}
/**
* Checks if a button on the given line is visible or not.
*
* @param {HTMLElement|Integer} lineOrIndex the line (or its index) to test its the button visibility
* @param {string} buttonName could be 'add_quantity', 'remove_unit' or 'set'.
* @param {boolean} [shouldBeVisible=true]
*/
export function assertButtonIsVisible(lineOrIndex, buttonName, shouldBeVisible = true) {
const line = _getLineOrFail(lineOrIndex);
const button = line.querySelector(`.o_line_button.o_${buttonName}`);
const label = line.querySelector(".o_product_label,.package")?.innerText;
assert(
!!button,
shouldBeVisible,
`${label ? label + " line" : "Line"}'s button "${buttonName}" ${
shouldBeVisible ? "should" : "should not"
} be visible`
);
}
export function assertValidateVisible(expected) {
const validateButton = document.querySelector(".o_validate_page,.o_apply_page");
assert(!!validateButton, expected, "Validate visible");
}
export function assertValidateEnabled(expected) {
const validateButton = document.querySelector(".o_validate_page,.o_apply_page") || false;
assert(
validateButton && !validateButton.hasAttribute("disabled"),
expected,
"Validate enabled"
);
}
export function assertValidateIsHighlighted(expected) {
const validateButton = document.querySelector(".o_validate_page,.o_apply_page") || false;
const isHighlighted = validateButton && validateButton.classList.contains("btn-primary");
assert(isHighlighted, expected, "Validate button is highlighted");
}
export function assertLinesCount(expectedCount, description) {
const currentCount = getLines(description).length;
assert(currentCount, expectedCount, `Should have ${expectedCount} line(s)`);
}
export function assertScanMessage(expected) {
const instruction = document.querySelector(`.o_scan_message`);
const cssClass = instruction.classList[1];
assert(cssClass, `o_${expected}`, "Not the right message displayed");
}
export function assertSublinesCount(expected) {
const current = document.querySelectorAll(".o_sublines > .o_barcode_line").length;
assert(current, expected, `Should have ${expected} subline(s), found ${current}`);
}
export function assertLineDestinationIsNotVisible(lineOrIndex) {
const line = _getLineOrFail(lineOrIndex);
const destinationElement = line.querySelector(".o_line_destination_location");
if (destinationElement) {
const product = line.querySelector(".o_product_label").innerText;
fail(
`The destination for line of the product ${product} should not be visible, "${destinationElement.innerText}" instead`
);
}
}
/**
* Checks if the given line is going in the given location. Implies the destination is visible.
* @param {Element} lineOrIndex
* @param {string} location
*/
export function assertLineDestinationLocation(lineOrIndex, location) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's destination");
const destinationElement = line.querySelector(".o_line_destination_location");
const product = line.querySelector(".o_product_label").innerText;
if (!destinationElement) {
fail(`The destination (${location}) for line of the product ${product} is not visible`);
}
assert(
destinationElement.innerText,
location,
`The destination for line of product ${product} isn't in the right location`
);
}
export function assertLineIsHighlighted(lineOrIndex, expected = true) {
const line = _getLineOrFail(lineOrIndex, "Can't check if the line is highlighted");
const errorMessage = `line ${expected ? "should" : "shouldn't"} be highlighted`;
assert(line.classList.contains("o_highlight"), expected, errorMessage);
}
export function assertLineLocations(lineOrIndex, source = null, destination = null) {
const line = _getLineOrFail(lineOrIndex, "Can't check line's locations");
if (source) {
assertLineSourceLocation(line, source);
} else {
assertLineSourceIsNotVisible(line);
}
if (destination) {
assertLineDestinationLocation(line, destination);
} else {
assertLineDestinationIsNotVisible(line);
}
}
export function assertLineLot(lineOrIndex, lotName) {
const line = _getLineOrFail(lineOrIndex, "Can't check line's lot or serial number");
const lineLotName = line.querySelector(".o_line_lot_name").innerText;
assert(lineLotName, lotName, "Not the expected product");
}
export function assertLineProduct(lineOrIndex, productName) {
const line = _getLineOrFail(lineOrIndex, "Can't check line's product");
const lineProduct = line.querySelector(".o_product_label").innerText;
assert(lineProduct, productName, "Not the expected product");
}
/**
* Checks the quantity. It will get the done/counted quantity and will also
* checks the on the reserved/on hand quantity if there is one.
* Also, if the unit of measure is displayed, it will check that too.
*
* @param {(HTMLElement|integer)} lineOrIndex @see _getLineOrFail
* @param {string} expectedQuantityWithUOM quantity on the line, formatted as "n (/ N) ( UOM)"
*/
export function assertLineQty(lineOrIndex, expectedQuantityWithUOM) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's quantity");
const elQty = line.querySelector(".o_barcode_scanner_qty");
const elUOM = line.querySelector(".o_line_uom");
let qtyText = elQty.innerText;
let errorMessage = "Something wrong with the quantities";
if (elUOM) {
qtyText += " " + elUOM.innerText;
errorMessage += " or with the Unit of Measure";
}
assert(qtyText, expectedQuantityWithUOM, errorMessage);
}
/**
* Checks the package assigned to a line. The expected package can be let
* empty to check there is no package assigned on the line.
* @param {(HTMLElement|integer)} lineOrIndex @see _getLineOrFail
* @param {string} [expectedPackageName]
*/
export function assertLinePackage(lineOrIndex, expectedPackageName = false) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's result package");
const packageEl = line.querySelector("div[name='package'] > .package");
if (!packageEl) {
if (expectedPackageName) {
fail(`There is no package: ${expectedPackageName} expected`);
}
} else {
const linePackageName = packageEl.innerText;
assert(linePackageName, expectedPackageName, "Not the expected line's package");
}
}
/**
* Checks the result package assigned to a line. The expected package can be let
* empty to check there is no result package assigned on the line.
* @param {(HTMLElement|integer)} lineOrIndex @see _getLineOrFail
* @param {string} [expectedPackageName]
*/
export function assertLineResultPackage(lineOrIndex, expectedPackageName = false) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's result package");
const resultPackageEl = line.querySelector(".result-package");
if (!resultPackageEl) {
if (expectedPackageName) {
fail(`There is no result package: ${expectedPackageName} expected`);
}
} else {
const linePackageName = resultPackageEl.innerText;
assert(linePackageName, expectedPackageName, "Not the expected result package");
}
}
export function assertLinePackages(lineOrIndex, expectedSrcPackageName, expectedResultPackageName) {
assertLinePackage(lineOrIndex, expectedSrcPackageName);
assertLineResultPackage(lineOrIndex, expectedResultPackageName);
}
export function assertLineSourceIsNotVisible(lineOrIndex) {
const line = _getLineOrFail(lineOrIndex);
const sourceElement = line.parentNode.querySelector(".o_barcode_location_line");
if (sourceElement) {
const product = line.querySelector(".o_product_label").innerText;
fail(
`The location for line of the product ${product} should not be visible, "${sourceElement.innerText}" instead`
);
}
}
/**
* Checks the given lot or serial number is written on the given line.
* Can also check none is written too.
*
* @param {(HTMLElement|integer)} lineOrIndex @see _getLineOrFail
* @param {string|Boolean} expectedTrackingNumber either the expected lot/serial
* number (or an empty string if the lot is displayed but empty), either false
* if the element shouldn't be visible at all.
*/
export function assertLineTrackingNumber(lineOrIndex, expectedTrackingNumber) {
const line = _getLineOrFail(lineOrIndex);
const elTrackingNumber = line.querySelector(".o_line_lot_name");
const product = line.querySelector(".product-label")?.innerText || "";
if (expectedTrackingNumber === false) {
assert(
!!elTrackingNumber,
false,
`No tracking number should be visible on the ${product} line`
);
} else {
assert(
!!elTrackingNumber,
true,
`${expectedTrackingNumber} should be visible but there is no tracking number on the ${product} line`
);
assert(
elTrackingNumber.innerText,
expectedTrackingNumber,
`Not the expected tracking number for the ${product} line`
);
}
}
/**
* Checks each given lines match the corresponding tracking numbers.
* The number of lines and tracking numbers has to be equals.
* @param {HTMLElement[]} lines
* @param {string[]} trackingNumbers
*/
export function assertLinesTrackingNumbers(lines, trackingNumbers) {
assert(
lines.length,
trackingNumbers.length,
"Not the same amount of lines and tracking numbers"
);
for (const [index, line] of lines.entries()) {
assertLineTrackingNumber(line, trackingNumbers[index]);
}
}
/**
* Checks if the given line is in the given location. Implies the location is visible.
* @param {Element} lineOrIndex
* @param {string} location
*/
export function assertLineSourceLocation(lineOrIndex, location) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's source");
const sourceElement = line.parentNode.querySelector(".o_barcode_location_line");
const product = line.querySelector(".o_product_label").innerText;
if (!sourceElement) {
fail(`The source (${location}) for line of the product ${product} is not visible`);
}
assert(
sourceElement.innerText,
location,
`The source for line of product ${product} isn't in the right location`
);
}
export function assertLineDescription(lineOrIndex, description) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's description");
const descriptionElement = line.querySelector("div[name='description']");
assert(descriptionElement.innerText, description, "Wrong description");
}
export function assertFormLocationSrc(expected) {
const location = document.querySelector('.o_field_widget[name="location_id"] input');
assert(location.value, expected, "Wrong source location");
}
export function assertFormLocationDest(expected) {
const location = document.querySelector('.o_field_widget[name="location_dest_id"] input');
assert(location.value, expected, "Wrong destination location");
}
export function assertFormQuantity(expected) {
const quantityField = document.querySelector(
'.o_field_widget[name="inventory_quantity"] input, .o_field_widget[name="qty_done"] input'
);
assert(quantityField.value, expected, "Wrong quantity");
}
export function assertKanbanRecordsCount(expected) {
const kanbanRecords = document.querySelectorAll(
".o_kanban_view .o_kanban_record:not(.o_kanban_ghost)"
);
assert(kanbanRecords.length, expected, "Wrong number of cards");
}
export function assertLineIsFaulty(lineOrIndex, expected = true) {
const line = _getLineOrFail(lineOrIndex, "Can't check if the line is faulty");
const errorMessage = `line ${expected ? "should" : "shouldn't"} be faulty`;
assert(line.classList.contains("o_faulty"), expected, errorMessage);
}
/**
* @param {(HTMLElement|integer)} lineOrIndex @see _getLineOrFail
* @param {string} packagingQuantity packaging quantity on the line, formatted as "n UOM"
*/
export function assertLinePackaging(lineOrIndex, packagingQuantity) {
const line = _getLineOrFail(lineOrIndex, "Can't check the line's packaging");
const elPackaging = line.querySelector(".o_packaging");
const packagingText = elPackaging.innerText;
assert(packagingText, `Packaging: ${packagingQuantity}`, "Line packaging not matching");
}