관망도 레이어 전체켜기 기능 추가
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const test = require('node:test');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const vm = require('node:vm');
|
||||
const ts = require('typescript');
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const source = fs.readFileSync(path.join(root, 'src/shared/ui/grid-cell-tooltip.tsx'), 'utf8');
|
||||
const css = fs.readFileSync(path.join(root, 'src/app/styles/grid-ellipsis.css'), 'utf8');
|
||||
|
||||
function mount() {
|
||||
const handlers = {};
|
||||
let cleanup;
|
||||
class Cell {
|
||||
constructor(text, overflowing = true) { this.textContent = text; this.title = ''; this.clientWidth = 100; this.scrollWidth = overflowing ? 300 : 100; }
|
||||
closest() { return this; }
|
||||
querySelector() { return null; }
|
||||
querySelectorAll() { return []; }
|
||||
hasAttribute() { return Boolean(this.title); }
|
||||
removeAttribute() { this.title = ''; }
|
||||
}
|
||||
const module = {exports:{}};
|
||||
vm.runInNewContext(ts.transpileModule(source, {compilerOptions:{module:ts.ModuleKind.CommonJS}}).outputText, {
|
||||
module, exports:module.exports, Element:Cell,
|
||||
require:()=>({useEffect:fn=>{cleanup=fn();}}),
|
||||
document:{addEventListener:(name,handler)=>{handlers[name]=handler;},removeEventListener:name=>{delete handlers[name];}},
|
||||
});
|
||||
module.exports.GridCellTooltip();
|
||||
return {Cell,handlers,cleanup};
|
||||
}
|
||||
test('CSS and tooltip target the same SN text cells and preserve controls', () => {
|
||||
const selector = source.match(/const CELL_SELECTOR = '([^']+)'/)[1];
|
||||
assert.ok(css.includes(selector + ' {'));
|
||||
for (const token of ['input','textarea','button','[colspan]','[rowspan]','data-sn-cell-wrap']) assert.ok(selector.includes(token));
|
||||
});
|
||||
test('overflow tooltip retains full text and updates reused cells', () => {
|
||||
const {Cell,handlers,cleanup}=mount(); const cell=new Cell('긴 원문\n내용');
|
||||
handlers.pointerover({target:cell}); assert.equal(cell.title,cell.textContent);
|
||||
cell.textContent='변경된 원문'; handlers.pointerover({target:cell}); assert.equal(cell.title,cell.textContent);
|
||||
cell.scrollWidth=100; handlers.pointerover({target:cell}); assert.equal(cell.title,'');
|
||||
cleanup(); assert.deepEqual(handlers,{});
|
||||
});
|
||||
test('existing explicit tooltip and editable-cell exclusions remain authoritative', () => {
|
||||
const {Cell,handlers}=mount(); const cell=new Cell('원문'); cell.title='기존 설명';
|
||||
handlers.pointerover({target:cell}); assert.equal(cell.title,'기존 설명');
|
||||
const excluded=new Cell('입력'); excluded.closest=()=>null;
|
||||
handlers.pointerover({target:excluded}); assert.equal(excluded.title,'');
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const test = require('node:test');
|
||||
const { pathToFileURL } = require('node:url');
|
||||
const path = require('node:path');
|
||||
const moduleUrl = pathToFileURL(path.resolve(__dirname, '../../../packages/common/business_components/src/ui/map/layerBulkSelection.js'));
|
||||
|
||||
test('toggle state follows all, partial, off and empty selections', async () => {
|
||||
const { getBulkLayerState } = await import(moduleUrl.href);
|
||||
const nodes = [{id:'a',data:{exprsYn:'Y'}},{id:'b',data:{exprsYn:'Y'}},{id:'h',data:{exprsYn:'N'}}];
|
||||
assert.deepEqual(getBulkLayerState(nodes, []), {disabled:false,allChecked:false,partiallyChecked:false});
|
||||
assert.deepEqual(getBulkLayerState(nodes, ['a']), {disabled:false,allChecked:false,partiallyChecked:true});
|
||||
assert.deepEqual(getBulkLayerState(nodes, ['a','b']), {disabled:false,allChecked:true,partiallyChecked:false});
|
||||
assert.deepEqual(getBulkLayerState([], []), {disabled:true,allChecked:false,partiallyChecked:false});
|
||||
});
|
||||
|
||||
test('bulk on checks visible parents and children, excluding hidden nodes', async () => {
|
||||
const { getBulkLayerSelection } = await import(moduleUrl.href);
|
||||
const nodes = [{id:1,data:{exprsYn:'Y'}},{id:2,parent:1,data:{exprsYn:'Y'}},{id:3,data:{exprsYn:'N'}}];
|
||||
const result = getBulkLayerSelection(nodes, true);
|
||||
assert.deepEqual(result.checkedIds, [1,2]);
|
||||
assert.deepEqual(result.uncheckedIds, [3]);
|
||||
assert.deepEqual(result.selectedNodes, nodes.slice(0,2));
|
||||
});
|
||||
test('bulk off clears every registered tree layer, without mutating input', async () => {
|
||||
const { getBulkLayerSelection } = await import(moduleUrl.href);
|
||||
const nodes = [{id:'a',data:{exprsYn:'Y'}},{id:'hidden',data:{exprsYn:'N'}}];
|
||||
assert.deepEqual(getBulkLayerSelection(nodes, false), {checkedIds:[],selectedNodes:[],uncheckedIds:['a','hidden']});
|
||||
assert.equal(nodes[0].data.exprsYn, 'Y');
|
||||
assert.deepEqual(getBulkLayerSelection([], true), {checkedIds:[],selectedNodes:[],uncheckedIds:[]});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const vm = require('node:vm');
|
||||
const test = require('node:test');
|
||||
const ts = require('typescript');
|
||||
|
||||
const appRoot = path.resolve(__dirname, '..');
|
||||
const source = fs.readFileSync(path.join(appRoot, 'src/shared/lib/row-number.ts'), 'utf8');
|
||||
const compiled = ts.transpileModule(source, {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS },
|
||||
}).outputText;
|
||||
const moduleValue = { exports: {} };
|
||||
vm.runInNewContext(compiled, { exports: moduleValue.exports, module: moduleValue });
|
||||
const { getSnRowNumber } = moduleValue.exports;
|
||||
|
||||
test('non-paged rows start at one and do not depend on total count', () => {
|
||||
assert.deepEqual([0, 1, 2].map(rowIndex => getSnRowNumber({total: 50, rowIndex})), [1, 2, 3]);
|
||||
assert.equal(getSnRowNumber({total: 0, rowIndex: 0}), 1);
|
||||
});
|
||||
test('server pages continue numbering and preserve the final partial page', () => {
|
||||
assert.equal(getSnRowNumber({total: 23, rowIndex: 0, pageIndex: 0, pageSize: 10}), 1);
|
||||
assert.equal(getSnRowNumber({total: 23, rowIndex: 0, pageIndex: 1, pageSize: 10}), 11);
|
||||
assert.equal(getSnRowNumber({total: 23, rowIndex: 2, pageIndex: 2, pageSize: 10}), 23);
|
||||
});
|
||||
test('page-size changes and refreshed result order use the new positions', () => {
|
||||
assert.equal(getSnRowNumber({rowIndex: 0, pageIndex: 1, pageSize: 20}), 21);
|
||||
assert.equal(getSnRowNumber({rowIndex: 0, pageIndex: 0, pageSize: 20}), 1);
|
||||
});
|
||||
|
||||
function sourceFiles(directory) {
|
||||
return fs.readdirSync(directory, {withFileTypes: true}).flatMap(entry => {
|
||||
const full = path.join(directory, entry.name);
|
||||
return entry.isDirectory() ? sourceFiles(full) : /\.tsx?$/.test(entry.name) ? [full] : [];
|
||||
});
|
||||
}
|
||||
test('SN does not use the shared descending helper or legacy descending row formulas', () => {
|
||||
for (const file of [...sourceFiles(path.join(appRoot, 'src')), ...sourceFiles(path.join(appRoot, 'app'))]) {
|
||||
const text = fs.readFileSync(file, 'utf8');
|
||||
assert.doesNotMatch(text, /getStandardRowNumber/, file);
|
||||
assert.doesNotMatch(text, /(?:rowNumber|rowNo|no)\s*:\s*(?:[\w.]+\s*-\s*(?:index|detailIndex)|total\w*\s*-)/, file);
|
||||
assert.doesNotMatch(text, /total(?:Elements|Count)?\s*-\s*\(\(?[^;{}\n]*(?:index|sourceIndex)/, file);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user