[deploy] Update URLSearchParams to handle arrays correctly for Rails (#7300)
This commit is contained in:
parent
2c6a4b4ecf
commit
223703f0d3
5 changed files with 62 additions and 33 deletions
|
|
@ -3,12 +3,14 @@ class SearchController < ApplicationController
|
|||
before_action :format_integer_params
|
||||
before_action :sanitize_params, only: %i[classified_listings]
|
||||
|
||||
CLASSIFIED_LISTINGS_PARAMS = %i[
|
||||
category
|
||||
classified_listing_search
|
||||
page
|
||||
per_page
|
||||
tags
|
||||
CLASSIFIED_LISTINGS_PARAMS = [
|
||||
:category,
|
||||
:classified_listing_search,
|
||||
:page,
|
||||
:per_page,
|
||||
{
|
||||
tags: []
|
||||
},
|
||||
].freeze
|
||||
|
||||
USER_PARAMS = %i[
|
||||
|
|
@ -17,15 +19,17 @@ class SearchController < ApplicationController
|
|||
per_page
|
||||
].freeze
|
||||
|
||||
FEED_PARAMS = %i[
|
||||
page
|
||||
per_page
|
||||
published_at
|
||||
search_fields
|
||||
sort_by
|
||||
tag_names
|
||||
user_id
|
||||
class_name
|
||||
FEED_PARAMS = [
|
||||
:class_name,
|
||||
:page,
|
||||
:per_page,
|
||||
:search_fields,
|
||||
:sort_by,
|
||||
:user_id,
|
||||
{
|
||||
tag_names: [],
|
||||
published_at: [:gte]
|
||||
},
|
||||
].freeze
|
||||
|
||||
def tags
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
hasInstantClick,
|
||||
displaySearchResults,
|
||||
fetchSearch,
|
||||
createSearchUrl,
|
||||
} from '../search';
|
||||
import '../../../../assets/javascripts/lib/xss';
|
||||
|
||||
|
|
@ -61,7 +62,7 @@ describe('Search utilities', () => {
|
|||
describe('preloadSearchResults', () => {
|
||||
beforeEach(() => {
|
||||
global.InstantClick = {
|
||||
preload: url => url,
|
||||
preload: (url) => url,
|
||||
};
|
||||
jest.spyOn(InstantClick, 'preload');
|
||||
});
|
||||
|
|
@ -145,7 +146,7 @@ describe('Search utilities', () => {
|
|||
describe('displaySearchResults', () => {
|
||||
beforeEach(() => {
|
||||
global.InstantClick = {
|
||||
display: url => url,
|
||||
display: (url) => url,
|
||||
};
|
||||
jest.spyOn(InstantClick, 'display');
|
||||
});
|
||||
|
|
@ -242,10 +243,18 @@ describe('Search utilities', () => {
|
|||
});
|
||||
|
||||
test('should return response formatted as JSON', () => {
|
||||
responsePromise.then(response => {
|
||||
responsePromise.then((response) => {
|
||||
expect(response).toBeInstanceOf(Object);
|
||||
expect(response).toMatchObject({ results: expect.any(Array) });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createSearchUrl', () => {
|
||||
test('should return a url string', () => {
|
||||
const dataHash = { name: 'jav', tags: ['one', 'two'] };
|
||||
const responseString = createSearchUrl(dataHash);
|
||||
expect(responseString).toEqual('name=jav&tags%5B%5D=one&tags%5B%5D=two');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ function fixedEncodeURIComponent(str) {
|
|||
// from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
|
||||
return encodeURIComponent(str).replace(
|
||||
/[!'()*]/g,
|
||||
c => `%${c.charCodeAt(0).toString(16)}`,
|
||||
(c) => `%${c.charCodeAt(0).toString(16)}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +79,22 @@ export function preloadSearchResults({
|
|||
);
|
||||
}
|
||||
|
||||
export function createSearchUrl(dataHash) {
|
||||
const searchParams = new URLSearchParams();
|
||||
Object.keys(dataHash).forEach((key) => {
|
||||
const value = dataHash[key];
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((arrayValue) => {
|
||||
searchParams.append(`${key}[]`, arrayValue);
|
||||
});
|
||||
} else {
|
||||
searchParams.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return searchParams.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method to call /search endpoints.
|
||||
*
|
||||
|
|
@ -88,9 +104,9 @@ export function preloadSearchResults({
|
|||
* @returns {Promise} A promise object with response formatted as JSON.
|
||||
*/
|
||||
export function fetchSearch(endpoint, dataHash) {
|
||||
const searchParams = new URLSearchParams(dataHash).toString();
|
||||
const searchUrl = createSearchUrl(dataHash);
|
||||
|
||||
return fetch(`/search/${endpoint}?${searchParams}`, {
|
||||
return fetch(`/search/${endpoint}?${searchUrl}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
|
|
@ -98,5 +114,5 @@ export function fetchSearch(endpoint, dataHash) {
|
|||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
}).then(response => response.json());
|
||||
}).then((response) => response.json());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ module Search
|
|||
TERM_KEYS.map do |term_key|
|
||||
next unless @params.key? term_key
|
||||
|
||||
{ term: { term_key => @params[term_key] } }
|
||||
{ terms: { term_key => Array.wrap(@params[term_key]) } }
|
||||
end.compact
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ RSpec.describe Search::QueryBuilders::ClassifiedListing, type: :service do
|
|||
params = { category: "cfp", tags: ["beginner"], contact_via_connect: false }
|
||||
filter = described_class.new(params: params)
|
||||
exepcted_filters = [
|
||||
{ "term" => { "category" => "cfp" } },
|
||||
{ "term" => { "tags" => ["beginner"] } },
|
||||
{ "term" => { "contact_via_connect" => false } },
|
||||
{ "term" => { "published" => true } },
|
||||
{ "terms" => { "category" => ["cfp"] } },
|
||||
{ "terms" => { "tags" => ["beginner"] } },
|
||||
{ "terms" => { "contact_via_connect" => [false] } },
|
||||
{ "terms" => { "published" => [true] } },
|
||||
]
|
||||
expect(filter.as_hash.dig("query", "bool", "filter")).to match_array(exepcted_filters)
|
||||
end
|
||||
|
|
@ -34,7 +34,7 @@ RSpec.describe Search::QueryBuilders::ClassifiedListing, type: :service do
|
|||
exepcted_filters = [
|
||||
{ "range" => { "bumped_at" => Time.current } },
|
||||
{ "range" => { "expires_at" => 1.day.from_now } },
|
||||
{ "term" => { "published" => true } },
|
||||
{ "terms" => { "published" => [true] } },
|
||||
]
|
||||
expect(filter.as_hash.dig("query", "bool", "filter")).to match_array(exepcted_filters)
|
||||
end
|
||||
|
|
@ -60,8 +60,8 @@ RSpec.describe Search::QueryBuilders::ClassifiedListing, type: :service do
|
|||
}]
|
||||
exepcted_filters = [
|
||||
{ "range" => { "bumped_at" => Time.current } },
|
||||
{ "term" => { "category" => "cfp" } },
|
||||
{ "term" => { "published" => true } },
|
||||
{ "terms" => { "category" => ["cfp"] } },
|
||||
{ "terms" => { "published" => [true] } },
|
||||
]
|
||||
expect(filter.as_hash.dig("query", "bool", "must")).to match_array(exepcted_query)
|
||||
expect(filter.as_hash.dig("query", "bool", "filter")).to match_array(exepcted_filters)
|
||||
|
|
@ -72,8 +72,8 @@ RSpec.describe Search::QueryBuilders::ClassifiedListing, type: :service do
|
|||
params = { not_supported: "trash", category: "cfp" }
|
||||
filter = described_class.new(params: params)
|
||||
exepcted_filters = [
|
||||
{ "term" => { "category" => "cfp" } },
|
||||
{ "term" => { "published" => true } },
|
||||
{ "terms" => { "category" => ["cfp"] } },
|
||||
{ "terms" => { "published" => [true] } },
|
||||
]
|
||||
expect(filter.as_hash.dig("query", "bool", "filter")).to match_array(exepcted_filters)
|
||||
end
|
||||
|
|
@ -82,7 +82,7 @@ RSpec.describe Search::QueryBuilders::ClassifiedListing, type: :service do
|
|||
filter = described_class.new(params: {}).as_hash
|
||||
expect(filter.dig("sort")).to eq("bumped_at" => "desc")
|
||||
expect(filter.dig("size")).to eq(0)
|
||||
expect(filter.dig("query", "bool", "filter")).to match_array([{ "term" => { "published" => true } }])
|
||||
expect(filter.dig("query", "bool", "filter")).to match_array([{ "terms" => { "published" => [true] } }])
|
||||
end
|
||||
|
||||
it "allows default params to be overriden" do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue