/** * 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( '' + '" + '
' + '
' + '
' + '
' ); // 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 {}; });