Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor the setHash function #1006

Merged
merged 14 commits into from
Mar 5, 2024
2 changes: 1 addition & 1 deletion benchexec/tablegenerator/react-table/build/main.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ const Table = (props) => {
const value = sort.length ? sort : undefined;
const prevParams = getHashSearch();
if (prevParams["sort"] !== value) {
setHashSearch({ sort: value }, { keepOthers: true });
setHashSearch({ sort: value }, true);
EshaanAgg marked this conversation as resolved.
Show resolved Hide resolved
}
}, [sortBy]);

Expand All @@ -600,7 +600,7 @@ const Table = (props) => {
const value = pageSize !== initialPageSize ? pageSize : undefined;
const prevParams = getHashSearch();
if (prevParams["pageSize"] !== value) {
setHashSearch({ pageSize: value }, { keepOthers: true });
setHashSearch({ pageSize: value }, true);
}
}, [pageSize]);

Expand All @@ -610,7 +610,7 @@ const Table = (props) => {
pageIndex && pageIndex !== 0 ? Number(pageIndex) + 1 : undefined;
const prevParams = getHashSearch();
if (prevParams["page"] !== value) {
setHashSearch({ page: value }, { keepOthers: true });
setHashSearch({ page: value }, true);
}
}, [pageIndex]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,7 @@ export default class SelectColumn extends React.Component {
hiddenParams["hidden"] = null;
}

setHashSearch(hiddenParams, {
keepOthers: true,
history: this.props.history,
});
setHashSearch(hiddenParams, true, this.props.history);
}

// -------------------------Rendering-------------------------
Expand Down
71 changes: 61 additions & 10 deletions benchexec/tablegenerator/react-table/src/tests/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import {
numericSortMethod,
textSortMethod,
getHashSearch,
setHashSearch,
NumberFormatterBuilder,
constructQueryString,
decodeFilter,
hasSameEntries,
getHashURL,
makeFilterSerializer,
makeFilterDeserializer,
splitUrlPathForMatchingPrefix,
decodeFilter,
} from "../utils/utils";

describe("isStatusOk", () => {
Expand Down Expand Up @@ -108,14 +109,64 @@ describe("hashRouting helpers", () => {
});
});

describe("setHashSearch", () => {
test("should translate object to queryparams", () => {
const params = { id: "1", name: "benchexec" };
const res = setHashSearch(params, {
returnString: true,
baseUrl: "localhost#table",
});
expect(res).toEqual("localhost#table?id=1&name=benchexec");
describe("constructQueryString", () => {
test("should return empty string for empty input", () => {
const queryString = constructQueryString({});
expect(queryString).toBe("");
});

test("should construct query string properly", () => {
const params = { key1: "value1", key2: "value2" };
const queryString = constructQueryString(params);
expect(queryString).toBe("key1=value1&key2=value2");
});

test("should omit undefined and null values", () => {
const params = { key1: "value1", key2: undefined, key3: null };
const queryString = constructQueryString(params);
expect(queryString).toBe("key1=value1");
});
});

describe("getHashURL", () => {
test("should construct URL hash with provided parameters", () => {
const baseUrl = "http://example.com";
EshaanAgg marked this conversation as resolved.
Show resolved Hide resolved
const params = { key1: "value1", key2: "value2" };
const keepOthers = false;

expect(getHashURL(baseUrl, params, keepOthers)).toEqual(
"http://example.com?key1=value1&key2=value2",
);
});

test("should construct URL hash with provided parameters and keep others", () => {
const baseUrl = "http://example.com?existingKey=existingValue";
const params = { key1: "value1", key2: "value2" };
const keepOthers = true;

expect(getHashURL(baseUrl, params, keepOthers)).toEqual(
"http://example.com?existingKey=existingValue&key1=value1&key2=value2",
);
});

test("should return the same URL with exisiting params if no parameters are provided and keepOthers is true", () => {
const baseUrl = "http://example.com?exisitingKey=existingValue";
const params = {};
const keepOthers = true;

expect(getHashURL(baseUrl, params, keepOthers)).toEqual(
"http://example.com?exisitingKey=existingValue",
);
});

test("should return the same URL with no params if no parameters are provided and keepOthers is false", () => {
const baseUrl = "http://example.com?exisitingKey=existingValue";
const params = {};
const keepOthers = false;

expect(getHashURL(baseUrl, params, keepOthers)).toEqual(
"http://example.com",
);
EshaanAgg marked this conversation as resolved.
Show resolved Hide resolved
});
});
});
Expand Down
98 changes: 54 additions & 44 deletions benchexec/tablegenerator/react-table/src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,68 +203,78 @@ const EXTENDED_DISCRETE_COLOR_RANGE = [
];

/**
* Parses the search parameters from the URL hash or a provided string.
*
* @param {String} [str]
* @param {string} - Optional string to parse. If not provided, parses the URL hash of the current document.
* @returns {Object} - An object containing the parsed search parameters.
*/
const getHashSearch = (str) => {
// Split the URL string into parts using "?" as a delimiter
const urlParts = (str || decodeURI(document.location.href)).split("?");

// Extract the search part of the URL
const search = urlParts.length > 1 ? urlParts.slice(1).join("?") : undefined;
if (search === undefined || search.length === 0) {
return {};
}
const keyValuePairs = search.split("&").map((i) => i.split("="));

// If there are no search parameters, return an empty object
if (search === undefined || search.length === 0) return {};
EshaanAgg marked this conversation as resolved.
Show resolved Hide resolved

// Split the search string into key-value pairs and generate an object from them
const keyValuePairs = search.split("&").map((pair) => pair.split("="));
const out = {};
for (const [key, ...value] of keyValuePairs) {
out[key] = value.join("=");
}

return out;
};

/**
* Constructs a query string from the provided parameters
*
* @param {Object} params - The parameters to be included in the query string. Any undefined or null values will be omitted.
* @returns {string} - The constructed query string.
*/
export const constructQueryString = (params) => {
return Object.keys(params)
.filter((key) => params[key] !== undefined && params[key] !== null)
.map((key) => `${key}=${params[key]}`)
.join("&");
EshaanAgg marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* Constructs a URL hash from the provided parameters
*
* @param {Object} params Object containing the params to be encoded as query params
* @param {Boolean} [returnString] if true, only returns the url without setting it
* @param {string} url - The URL to be processed
* @param {Object} params - The parameters to be included in the hash
* @param {boolean} [keepOthers=false] - Whether to keep existing parameters in the URL hash or not
* @returns {string} - The constructed URL hash
*/
export const getHashURL = (url, params = {}, keepOthers = false) => {
EshaanAgg marked this conversation as resolved.
Show resolved Hide resolved
const additionalParams = keepOthers ? getHashSearch(url) : {};
const mergedParams = { ...additionalParams, ...params };

const queryString = constructQueryString(mergedParams);
const baseURL = url.split("?")[0];

return queryString.length > 0 ? `${baseURL}?${queryString}` : baseURL;
};

/**
* Sets or updates the search parameters in the URL hash of the current page.
*
* @param {Object} params - The parameters to be set or updated in the URL hash
* @param {boolean} [keepOthers=false] - Whether to keep existing parameters in the URL hash or not
* @param {Object} [history=undefined] - The history object to be used for navigation
* @returns {void}
*/
const setHashSearch = (
params = {},
options = {
returnString: false,
baseUrl: null,
keepOthers: false,
paramName: null,
history: null,
},
keepOthers = false,
history = undefined,
) => {
let additionalParams = {};
let transformedParams = params;
if (options.keepOthers) {
additionalParams = getHashSearch();
const removedItems = Object.entries(params).filter(
([_, value]) => value === undefined || value === null,
);
removedItems.forEach(([key]) => {
delete additionalParams[key];
delete transformedParams[key];
});
}
const mergedParams = { ...additionalParams, ...params };
const optionTemplate = { returnString: false, baseUrl: null };
const { returnString, baseUrl, history } = { ...optionTemplate, ...options };
const url = (baseUrl || document.location.href).split("?")[0];
const pairs = Object.keys(mergedParams).map(
(key) => `${key}=${mergedParams[key]}`,
);
const searchString = `?${pairs.join("&")}`;
const hrefString = encodeURI(`${url}${searchString}`);
if (returnString) {
return hrefString;
}
if (history) {
history.push(searchString);
return;
}
document.location.href = hrefString;
const newUrl = getHashURL(document.location.href, params, keepOthers);
if (history) history.push(newUrl);
document.location.href = newUrl;
};

const makeUrlFilterDeserializer = (statusValues, categoryValues) => {
Expand Down Expand Up @@ -672,7 +682,7 @@ const setConstantHashSearch = (paramString) => {
* @param {Object} param The Key-Value pair to be added to the current query param list
*/
const setParam = (param) => {
setHashSearch({ ...getHashSearch(), ...param });
setHashSearch(param, true);
};

const stringAsBoolean = (str) => str === "true";
Expand Down
Loading