mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-04-07 07:36:58 +00:00
Add tests for Select2AjaxController with AJAX functionality
This commit is contained in:
@@ -370,4 +370,153 @@ RSpec.describe Admin::ReportsController do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "AJAX Search" do
|
||||
let(:enterprise_fee1) {
|
||||
create(:enterprise_fee, name: "Delivery Fee", enterprise: distributor1)
|
||||
}
|
||||
let(:enterprise_fee2) { create(:enterprise_fee, name: "Admin Fee", enterprise: distributor2) }
|
||||
|
||||
before do
|
||||
controller_login_as_admin
|
||||
orderA1.adjustments.create!(
|
||||
originator: enterprise_fee1,
|
||||
label: "Delivery Fee",
|
||||
amount: 5.0,
|
||||
state: "finalized",
|
||||
order: orderA1
|
||||
)
|
||||
orderB1.adjustments.create!(
|
||||
originator: enterprise_fee2,
|
||||
label: "Admin Fee",
|
||||
amount: 3.0,
|
||||
state: "finalized",
|
||||
order: orderB1
|
||||
)
|
||||
end
|
||||
|
||||
describe "#search_enterprise_fees" do
|
||||
it "returns paginated JSON with enterprise fees ordered by name" do
|
||||
spree_get(
|
||||
:search_enterprise_fees,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order
|
||||
)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json_response = response.parsed_body
|
||||
|
||||
names = json_response["results"].pluck("text")
|
||||
expect(names).to eq(['Admin Fee', 'Delivery Fee'])
|
||||
end
|
||||
|
||||
it "caches and works with different report types" do
|
||||
spree_get(
|
||||
:search_enterprise_fees,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order
|
||||
)
|
||||
first_response = response.parsed_body
|
||||
|
||||
spree_get(
|
||||
:search_enterprise_fees,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order
|
||||
)
|
||||
second_response = response.parsed_body
|
||||
|
||||
expect(first_response).to eq(second_response)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#search_enterprise_fee_owners" do
|
||||
it "returns paginated JSON with unique enterprise owners ordered by name" do
|
||||
distributor1.update!(name: "Zebra Farm")
|
||||
distributor2.update!(name: "Alpha Market")
|
||||
|
||||
spree_get(
|
||||
:search_enterprise_fee_owners,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order
|
||||
)
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json_response = response.parsed_body
|
||||
|
||||
names = json_response["results"].pluck("text")
|
||||
expect(names).to eq(['Alpha Market', 'Zebra Farm'])
|
||||
end
|
||||
|
||||
it "caches results" do
|
||||
spree_get(
|
||||
:search_enterprise_fee_owners,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order
|
||||
)
|
||||
first_response = response.parsed_body
|
||||
|
||||
spree_get(
|
||||
:search_enterprise_fee_owners,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order
|
||||
)
|
||||
second_response = response.parsed_body
|
||||
|
||||
expect(first_response).to eq(second_response)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#search_order_customers" do
|
||||
it "filters customers by email and returns paginated results" do
|
||||
customer1 = create(:customer, email: "alice@example.com", enterprise: distributor1)
|
||||
customer2 = create(:customer, email: "bob@example.com", enterprise: distributor1)
|
||||
orderA1.update!(customer: customer1)
|
||||
orderA2.update!(customer: customer2)
|
||||
|
||||
spree_get(
|
||||
:search_order_customers,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order,
|
||||
q: "alice"
|
||||
)
|
||||
|
||||
json_response = response.parsed_body
|
||||
expect(json_response["results"].pluck("text")).to eq(["alice@example.com"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#search_order_cycles" do
|
||||
it "filters order cycles by name and orders by close date" do
|
||||
ocA.update!(name: "Winter Market")
|
||||
ocB.update!(name: "Summer Market")
|
||||
|
||||
spree_get(
|
||||
:search_order_cycles,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order,
|
||||
q: "Winter"
|
||||
)
|
||||
|
||||
json_response = response.parsed_body
|
||||
expect(json_response["results"].pluck("text")).to eq(["Winter Market"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#search_distributors" do
|
||||
it "filters distributors by name" do
|
||||
distributor1.update!(name: "Alpha Farm")
|
||||
distributor2.update!(name: "Beta Market")
|
||||
|
||||
spree_get(
|
||||
:search_distributors,
|
||||
report_type: :enterprise_fee_summary,
|
||||
report_subtype: :enterprise_fees_with_tax_report_by_order,
|
||||
q: "Alpha"
|
||||
)
|
||||
|
||||
json_response = response.parsed_body
|
||||
expect(json_response["results"].pluck("text")).to eq(["Alpha Farm"])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
156
spec/javascripts/stimulus/select2_ajax_controller_test.js
Normal file
156
spec/javascripts/stimulus/select2_ajax_controller_test.js
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
|
||||
import { Application } from "stimulus";
|
||||
import select2_ajax_controller from "../../../app/webpacker/controllers/select2_ajax_controller.js";
|
||||
|
||||
describe("Select2AjaxController", () => {
|
||||
let select2InitOptions = null;
|
||||
let application;
|
||||
|
||||
beforeAll(() => {
|
||||
application = Application.start();
|
||||
application.register("select2-ajax", select2_ajax_controller);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
select2InitOptions = null;
|
||||
|
||||
// Mock jQuery and select2
|
||||
const mockVal = jest.fn(function (value) {
|
||||
if (value !== undefined) {
|
||||
this._value = value;
|
||||
return this;
|
||||
}
|
||||
return this._value || "";
|
||||
});
|
||||
|
||||
const mockOn = jest.fn().mockReturnThis();
|
||||
|
||||
const mockSelect2 = jest.fn(function (options) {
|
||||
if (typeof options === "string" && options === "destroy") {
|
||||
return this;
|
||||
}
|
||||
select2InitOptions = options;
|
||||
return this;
|
||||
});
|
||||
|
||||
const jQueryMock = jest.fn((selector) => {
|
||||
let element;
|
||||
if (typeof selector === "string" && selector.startsWith("<input")) {
|
||||
element = document.createElement("input");
|
||||
element.type = "hidden";
|
||||
} else {
|
||||
element = selector;
|
||||
}
|
||||
|
||||
const jqObject = {
|
||||
val: mockVal,
|
||||
trigger: jest.fn().mockReturnThis(),
|
||||
select2: mockSelect2,
|
||||
hasClass: jest.fn().mockReturnValue(false),
|
||||
attr: jest.fn(function (name, value) {
|
||||
if (value !== undefined && element) {
|
||||
element.setAttribute(name, value);
|
||||
}
|
||||
return this;
|
||||
}),
|
||||
on: mockOn,
|
||||
0: element,
|
||||
_value: "",
|
||||
};
|
||||
|
||||
return jqObject;
|
||||
});
|
||||
|
||||
jQueryMock.fn = { select2: jest.fn() };
|
||||
global.$ = jQueryMock;
|
||||
|
||||
document.body.innerHTML = `
|
||||
<select
|
||||
id="test-select"
|
||||
name="test_name[]"
|
||||
data-controller="select2-ajax"
|
||||
data-select2-ajax-url-value="/api/search">
|
||||
<option value="">Select...</option>
|
||||
</select>
|
||||
`;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = "";
|
||||
delete global.$;
|
||||
});
|
||||
|
||||
describe("#connect", () => {
|
||||
it("initializes select2 with correct AJAX URL", () => {
|
||||
expect(select2InitOptions).not.toBeNull();
|
||||
expect(select2InitOptions.ajax.url).toBe("/api/search");
|
||||
});
|
||||
|
||||
it("configures select2 with correct options", () => {
|
||||
expect(select2InitOptions.ajax.dataType).toBe("json");
|
||||
expect(select2InitOptions.ajax.quietMillis).toBe(300);
|
||||
expect(select2InitOptions.allowClear).toBe(true);
|
||||
expect(select2InitOptions.minimumInputLength).toBe(0);
|
||||
expect(select2InitOptions.width).toBe("100%");
|
||||
});
|
||||
|
||||
it("configures AJAX data function", () => {
|
||||
const dataFunc = select2InitOptions.ajax.data;
|
||||
const result = dataFunc("search term", 2);
|
||||
|
||||
expect(result).toEqual({
|
||||
q: "search term",
|
||||
page: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it("handles empty search term", () => {
|
||||
const dataFunc = select2InitOptions.ajax.data;
|
||||
const result = dataFunc(null, null);
|
||||
|
||||
expect(result).toEqual({
|
||||
q: "",
|
||||
page: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it("configures results function with pagination", () => {
|
||||
const resultsFunc = select2InitOptions.ajax.results;
|
||||
const mockData = {
|
||||
results: [{ id: 1, text: "Item 1" }],
|
||||
pagination: { more: true },
|
||||
};
|
||||
|
||||
const result = resultsFunc(mockData, 1);
|
||||
|
||||
expect(result).toEqual({
|
||||
results: mockData.results,
|
||||
more: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("handles missing pagination", () => {
|
||||
const resultsFunc = select2InitOptions.ajax.results;
|
||||
const mockData = {
|
||||
results: [{ id: 1, text: "Item 1" }],
|
||||
};
|
||||
|
||||
const result = resultsFunc(mockData, 1);
|
||||
|
||||
expect(result).toEqual({
|
||||
results: mockData.results,
|
||||
more: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("configures format functions", () => {
|
||||
const item = { id: 1, text: "Test Item" };
|
||||
|
||||
expect(select2InitOptions.formatResult(item)).toBe("Test Item");
|
||||
expect(select2InitOptions.formatSelection(item)).toBe("Test Item");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user