/** * 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 {}; });