- Remove redundant string= from 17 field definitions where name matches string value (W8113) - Convert @staticmethod to instance methods in selection methods for proper self.env._() access - Fix W8161 (prefer-env-translation) by using self.env._() instead of standalone _() - Fix W8301/W8115 (translation-not-lazy) by proper placement of % interpolation outside self.env._() - Remove unused imports of odoo._ from group_order.py and sale_order_extension.py - All OCA linting warnings in website_sale_aplicoop main models are now resolved Changes: - website_sale_aplicoop/models/group_order.py: 21 field definitions cleaned - website_sale_aplicoop/models/sale_order_extension.py: 5 field definitions cleaned + @staticmethod conversion - Consistent with OCA standards for addon submission
249 lines
10 KiB
JavaScript
249 lines
10 KiB
JavaScript
/**
|
|
* QUnit Tests for Realtime Search Functionality
|
|
* Tests product filtering and search behavior
|
|
*/
|
|
|
|
odoo.define("website_sale_aplicoop.test_realtime_search", function (require) {
|
|
"use strict";
|
|
|
|
var QUnit = window.QUnit;
|
|
|
|
QUnit.module(
|
|
"website_sale_aplicoop.realtime_search",
|
|
{
|
|
beforeEach: function () {
|
|
// Setup: Create test DOM with product cards
|
|
this.$fixture = $("#qunit-fixture");
|
|
|
|
this.$fixture.append(
|
|
'<input type="text" id="realtime-search-input" />' +
|
|
'<select id="realtime-category-select">' +
|
|
'<option value="">All Categories</option>' +
|
|
'<option value="1">Category 1</option>' +
|
|
'<option value="2">Category 2</option>' +
|
|
"</select>" +
|
|
'<div class="product-card" data-product-name="Cabbage" data-category-id="1"></div>' +
|
|
'<div class="product-card" data-product-name="Carrot" data-category-id="1"></div>' +
|
|
'<div class="product-card" data-product-name="Apple" data-category-id="2"></div>' +
|
|
'<div class="product-card" data-product-name="Banana" data-category-id="2"></div>'
|
|
);
|
|
|
|
// Initialize search object
|
|
window.realtimeSearch = {
|
|
searchInput: document.getElementById("realtime-search-input"),
|
|
categorySelect: document.getElementById("realtime-category-select"),
|
|
productCards: document.querySelectorAll(".product-card"),
|
|
|
|
filterProducts: function () {
|
|
var searchTerm = this.searchInput.value.toLowerCase().trim();
|
|
var selectedCategory = this.categorySelect.value;
|
|
|
|
var visibleCount = 0;
|
|
var hiddenCount = 0;
|
|
|
|
this.productCards.forEach(function (card) {
|
|
var productName = card.getAttribute("data-product-name").toLowerCase();
|
|
var categoryId = card.getAttribute("data-category-id");
|
|
|
|
var matchesSearch = !searchTerm || productName.includes(searchTerm);
|
|
var matchesCategory =
|
|
!selectedCategory || categoryId === selectedCategory;
|
|
|
|
if (matchesSearch && matchesCategory) {
|
|
card.classList.remove("d-none");
|
|
visibleCount++;
|
|
} else {
|
|
card.classList.add("d-none");
|
|
hiddenCount++;
|
|
}
|
|
});
|
|
|
|
return { visible: visibleCount, hidden: hiddenCount };
|
|
},
|
|
};
|
|
},
|
|
afterEach: function () {
|
|
// Cleanup
|
|
this.$fixture.empty();
|
|
delete window.realtimeSearch;
|
|
},
|
|
},
|
|
function () {
|
|
QUnit.test("search input element exists", function (assert) {
|
|
assert.expect(1);
|
|
|
|
var searchInput = document.getElementById("realtime-search-input");
|
|
assert.ok(searchInput, "search input element exists");
|
|
});
|
|
|
|
QUnit.test("category select element exists", function (assert) {
|
|
assert.expect(1);
|
|
|
|
var categorySelect = document.getElementById("realtime-category-select");
|
|
assert.ok(categorySelect, "category select element exists");
|
|
});
|
|
|
|
QUnit.test("product cards are found", function (assert) {
|
|
assert.expect(1);
|
|
|
|
var productCards = document.querySelectorAll(".product-card");
|
|
assert.equal(productCards.length, 4, "found 4 product cards");
|
|
});
|
|
|
|
QUnit.test("search filters by product name", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// Search for "cab"
|
|
window.realtimeSearch.searchInput.value = "cab";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 1, "1 product visible (Cabbage)");
|
|
assert.equal(result.hidden, 3, "3 products hidden");
|
|
});
|
|
|
|
QUnit.test("search is case insensitive", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// Search for "CARROT" in uppercase
|
|
window.realtimeSearch.searchInput.value = "CARROT";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 1, "1 product visible (Carrot)");
|
|
assert.equal(result.hidden, 3, "3 products hidden");
|
|
});
|
|
|
|
QUnit.test("empty search shows all products", function (assert) {
|
|
assert.expect(2);
|
|
|
|
window.realtimeSearch.searchInput.value = "";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 4, "all 4 products visible");
|
|
assert.equal(result.hidden, 0, "no products hidden");
|
|
});
|
|
|
|
QUnit.test("category filter works", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// Select category 1
|
|
window.realtimeSearch.categorySelect.value = "1";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 2, "2 products visible (Cabbage, Carrot)");
|
|
assert.equal(result.hidden, 2, "2 products hidden (Apple, Banana)");
|
|
});
|
|
|
|
QUnit.test("search and category filter work together", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// Search for "ca" in category 1
|
|
window.realtimeSearch.searchInput.value = "ca";
|
|
window.realtimeSearch.categorySelect.value = "1";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
// Should show: Cabbage, Carrot (both in category 1 and match "ca")
|
|
assert.equal(result.visible, 2, "2 products visible");
|
|
assert.equal(result.hidden, 2, "2 products hidden");
|
|
});
|
|
|
|
QUnit.test("search for non-existent product shows none", function (assert) {
|
|
assert.expect(2);
|
|
|
|
window.realtimeSearch.searchInput.value = "xyz123";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 0, "no products visible");
|
|
assert.equal(result.hidden, 4, "all 4 products hidden");
|
|
});
|
|
|
|
QUnit.test("partial match works", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// Search for "an" should match "Banana"
|
|
window.realtimeSearch.searchInput.value = "an";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 1, "1 product visible (Banana)");
|
|
assert.equal(result.hidden, 3, "3 products hidden");
|
|
});
|
|
|
|
QUnit.test("search trims whitespace", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// Search with extra whitespace
|
|
window.realtimeSearch.searchInput.value = " apple ";
|
|
var result = window.realtimeSearch.filterProducts();
|
|
|
|
assert.equal(result.visible, 1, "1 product visible (Apple)");
|
|
assert.equal(result.hidden, 3, "3 products hidden");
|
|
});
|
|
|
|
QUnit.test("d-none class is added to hidden products", function (assert) {
|
|
assert.expect(1);
|
|
|
|
window.realtimeSearch.searchInput.value = "cabbage";
|
|
window.realtimeSearch.filterProducts();
|
|
|
|
var productCards = document.querySelectorAll(".product-card");
|
|
var hiddenCards = Array.from(productCards).filter(function (card) {
|
|
return card.classList.contains("d-none");
|
|
});
|
|
|
|
assert.equal(hiddenCards.length, 3, "3 cards have d-none class");
|
|
});
|
|
|
|
QUnit.test("d-none class is removed from visible products", function (assert) {
|
|
assert.expect(2);
|
|
|
|
// First hide all
|
|
window.realtimeSearch.searchInput.value = "xyz";
|
|
window.realtimeSearch.filterProducts();
|
|
|
|
var allHidden = Array.from(window.realtimeSearch.productCards).every(function (
|
|
card
|
|
) {
|
|
return card.classList.contains("d-none");
|
|
});
|
|
assert.ok(allHidden, "all cards hidden initially");
|
|
|
|
// Then show all
|
|
window.realtimeSearch.searchInput.value = "";
|
|
window.realtimeSearch.filterProducts();
|
|
|
|
var allVisible = Array.from(window.realtimeSearch.productCards).every(function (
|
|
card
|
|
) {
|
|
return !card.classList.contains("d-none");
|
|
});
|
|
assert.ok(allVisible, "all cards visible after clearing search");
|
|
});
|
|
|
|
QUnit.test("filterProducts returns correct counts", function (assert) {
|
|
assert.expect(4);
|
|
|
|
// All visible
|
|
window.realtimeSearch.searchInput.value = "";
|
|
var result1 = window.realtimeSearch.filterProducts();
|
|
assert.equal(result1.visible + result1.hidden, 4, "total count is 4");
|
|
|
|
// 1 visible
|
|
window.realtimeSearch.searchInput.value = "apple";
|
|
var result2 = window.realtimeSearch.filterProducts();
|
|
assert.equal(result2.visible, 1, "visible count is 1");
|
|
|
|
// None visible
|
|
window.realtimeSearch.searchInput.value = "xyz";
|
|
var result3 = window.realtimeSearch.filterProducts();
|
|
assert.equal(result3.visible, 0, "visible count is 0");
|
|
|
|
// Category filter
|
|
window.realtimeSearch.searchInput.value = "";
|
|
window.realtimeSearch.categorySelect.value = "2";
|
|
var result4 = window.realtimeSearch.filterProducts();
|
|
assert.equal(result4.visible, 2, "category filter shows 2 products");
|
|
});
|
|
}
|
|
);
|
|
|
|
return {};
|
|
});
|