refactor shared frontend size parsing
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
||||
} from '../web/resolver/utils/category_aliases.generated.js';
|
||||
import { getSha256Field, normalizeSha256 } from '../web/resolver/utils/hash_utils.js';
|
||||
import { normalizeSearchToken } from '../web/resolver/utils/search_utils.js';
|
||||
import { parseFiniteNumber } from '../web/resolver/utils/size_utils.js';
|
||||
import { getSourceDisplayLabel, normalizeSourceKey } from '../web/resolver/utils/source_labels.js';
|
||||
import { baseModelAliasMethods } from '../web/resolver/search/base_model_alias_methods.js';
|
||||
import { searchHashMethods } from '../web/resolver/search/search_hash_methods.js';
|
||||
@@ -6963,6 +6964,50 @@ test('CivitAI hash search renders sizeKB when byte size is unavailable', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('search result size formatting preserves aliases and fallback values', () => {
|
||||
const formatSearchResultSize = eval(`(${extractMethod(searchPanelMethodsSource, 'formatSearchResultSize')})`);
|
||||
const dialog = {
|
||||
formatBytes(value) {
|
||||
return `${Number(value)} B`;
|
||||
},
|
||||
};
|
||||
|
||||
assert.equal(formatSearchResultSize.call(dialog, { size: 2048 }), '2048 B');
|
||||
assert.equal(formatSearchResultSize.call(dialog, { size: '5.7 GB' }), '5.7 GB');
|
||||
assert.equal(
|
||||
formatSearchResultSize.call(dialog, {
|
||||
size: null,
|
||||
file_info: { sizeBytes: 1024 },
|
||||
}),
|
||||
'1024 B'
|
||||
);
|
||||
assert.equal(formatSearchResultSize.call(dialog, { size: null, sizeKB: '2' }), '2048 B');
|
||||
assert.equal(formatSearchResultSize.call(dialog, { size: 0 }), '0 B');
|
||||
assert.equal(formatSearchResultSize.call(dialog, { size: null, sizeKB: 'invalid' }), '');
|
||||
assert.equal(formatSearchResultSize.call(dialog, { size: null, sizeKB: Number.MAX_VALUE }), '');
|
||||
});
|
||||
|
||||
test('info dialog size formatting preserves numeric, nested and label values', () => {
|
||||
const formatInfoDialogSize = eval(`(${extractMethod(modelInfoMethodsSource, 'formatInfoDialogSize')})`);
|
||||
const dialog = {
|
||||
formatBytes(value) {
|
||||
return `${Number(value)} B`;
|
||||
},
|
||||
};
|
||||
|
||||
assert.equal(formatInfoDialogSize.call(dialog, { size: 2048 }), '2048 B');
|
||||
assert.equal(formatInfoDialogSize.call(dialog, { size: '2048' }), '2048 B');
|
||||
assert.equal(
|
||||
formatInfoDialogSize.call(dialog, { file: { sizeBytes: 1024 } }),
|
||||
'1024 B'
|
||||
);
|
||||
assert.equal(formatInfoDialogSize.call(dialog, { size: '5.7 GB' }), '5.7 GB');
|
||||
assert.equal(formatInfoDialogSize.call(dialog, { size: 0 }), '0 B');
|
||||
assert.equal(formatInfoDialogSize.call(dialog, { size: '0' }), '0 B');
|
||||
assert.equal(formatInfoDialogSize.call(dialog, { size: 'invalid' }), 'invalid');
|
||||
assert.equal(formatInfoDialogSize.call(dialog, {}), '');
|
||||
});
|
||||
|
||||
test('link/name controls place the add or search action before the input switch', () => {
|
||||
const renderSearchControls = eval(`(${extractMethod(searchPanelMethodsSource, 'renderSearchControls')})`);
|
||||
const dialog = {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { parseFiniteNumber } from '../web/resolver/utils/size_utils.js';
|
||||
|
||||
test('parseFiniteNumber normalizes numeric size values', () => {
|
||||
assert.equal(parseFiniteNumber(2048), 2048);
|
||||
assert.equal(parseFiniteNumber('2048'), 2048);
|
||||
assert.equal(parseFiniteNumber('0'), 0);
|
||||
assert.equal(parseFiniteNumber(0), 0);
|
||||
});
|
||||
|
||||
test('parseFiniteNumber rejects empty, invalid and non-finite values', () => {
|
||||
assert.equal(parseFiniteNumber(null), null);
|
||||
assert.equal(parseFiniteNumber(undefined), null);
|
||||
assert.equal(parseFiniteNumber(''), null);
|
||||
assert.equal(parseFiniteNumber('invalid'), null);
|
||||
assert.equal(parseFiniteNumber(Infinity), null);
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import { getSourceDisplayLabel, normalizeSourceKey } from "../utils/source_label
|
||||
import { getCivitaiModelUrl } from "../globals.js";
|
||||
import { safeStorage, normalizePathIdentity } from "../utils/html_utils.js";
|
||||
import { getSha256Field } from "../utils/hash_utils.js";
|
||||
import { parseFiniteNumber } from "../utils/size_utils.js";
|
||||
import { bindEventOnce } from "../utils/dom_patch_utils.js";
|
||||
import {
|
||||
classifyLocalMatches,
|
||||
@@ -1552,8 +1553,8 @@ export const searchPanelMethods = {
|
||||
|
||||
const sizeKb = candidate.sizeKB ?? candidate.size_kb;
|
||||
if (sizeKb !== undefined && sizeKb !== null && sizeKb !== '') {
|
||||
const sizeBytes = Number(sizeKb) * 1024;
|
||||
if (Number.isFinite(sizeBytes)) return this.formatBytes(sizeBytes);
|
||||
const sizeBytes = parseFiniteNumber(sizeKb * 1024);
|
||||
if (sizeBytes !== null) return this.formatBytes(sizeBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export function parseFiniteNumber(value) {
|
||||
if (value === null || value === undefined || value === '') return null;
|
||||
|
||||
const numericValue = Number(value);
|
||||
return Number.isFinite(numericValue) ? numericValue : null;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { escapeHtml, escapeJsString, getFilenameFromPath, sanitizeDescriptionHtm
|
||||
import { getModelCardUrl } from "../utils/url_utils.js";
|
||||
import { extractComfyWorkflow } from "../utils/workflow_metadata.js";
|
||||
import { getSha256Field, normalizeSha256 } from "../utils/hash_utils.js";
|
||||
import { parseFiniteNumber } from "../utils/size_utils.js";
|
||||
import { getSourceDisplayLabel } from "../utils/source_labels.js";
|
||||
import { getCivitaiModelUrl } from "../globals.js";
|
||||
export const modelInfoMethods = {
|
||||
@@ -1263,8 +1264,8 @@ export const modelInfoMethods = {
|
||||
if (rawSize === null || rawSize === undefined || rawSize === '') return '';
|
||||
if (rawSize === 0 || rawSize === '0') return '0 B';
|
||||
|
||||
const numericSize = Number(rawSize);
|
||||
if (Number.isFinite(numericSize)) {
|
||||
const numericSize = parseFiniteNumber(rawSize);
|
||||
if (numericSize !== null) {
|
||||
return typeof this.formatBytes === 'function'
|
||||
? this.formatBytes(numericSize)
|
||||
: `${numericSize} B`;
|
||||
|
||||
Reference in New Issue
Block a user