Fix getters mutating state on repeated access
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -124,23 +124,22 @@ export const useAllMapDataStore = defineStore('allMapDataStore', {
|
||||
},
|
||||
filterAttrs: state => {
|
||||
if(state.allFilterAttrs !== null){
|
||||
state.allFilterAttrs.forEach(att => {
|
||||
switch (att.type) {
|
||||
return state.allFilterAttrs.map(att => {
|
||||
const copy = { ...att };
|
||||
switch (copy.type) {
|
||||
case 'date':
|
||||
att.min = att.min !== null ? moment(att.min).format('YYYY/MM/DD HH:mm') : null;
|
||||
att.max = att.max !== null ? moment(att.max).format('YYYY/MM/DD HH:mm') : null;
|
||||
copy.min = copy.min !== null ? moment(copy.min).format('YYYY/MM/DD HH:mm') : null;
|
||||
copy.max = copy.max !== null ? moment(copy.max).format('YYYY/MM/DD HH:mm') : null;
|
||||
break;
|
||||
case 'float':
|
||||
// Decimal.ROUND_UP|0: 無條件進位; Decimal.ROUND_DOWN|1: 無條件捨去。
|
||||
att.min = att.min !== null ? Number(new Decimal(att.min).toFixed(2, 1)) : null;
|
||||
att.max = att.max !== null ? Number(new Decimal(att.max).toFixed(2, 0)) : null;
|
||||
copy.min = copy.min !== null ? Number(new Decimal(copy.min).toFixed(2, 1)) : null;
|
||||
copy.max = copy.max !== null ? Number(new Decimal(copy.max).toFixed(2, 0)) : null;
|
||||
break
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return att;
|
||||
return copy;
|
||||
});
|
||||
return state.allFilterAttrs;
|
||||
}
|
||||
},
|
||||
allFunnels: state => {
|
||||
|
||||
@@ -163,38 +163,42 @@ export const useConformanceStore = defineStore('conformanceStore', {
|
||||
},
|
||||
cases: state => {
|
||||
if(state.allCases !== null){
|
||||
const newData = state.allCases.map(c => {
|
||||
c.started_at = moment(c.started_at).format('YYYY/MM/DD HH:mm');
|
||||
c.completed_at = moment(c.completed_at).format('YYYY/MM/DD HH:mm');
|
||||
c.facets.forEach(fac => {
|
||||
switch(fac.type) {
|
||||
return state.allCases.map(c => {
|
||||
const facets = c.facets.map(fac => {
|
||||
const copy = { ...fac };
|
||||
switch(copy.type) {
|
||||
case 'dummy': //sonar-qube
|
||||
case 'duration-list':
|
||||
fac.value = fac.value.map(v => v !== null ? abbreviateNumber(new Decimal(v.toFixed(2))) : null);
|
||||
fac.value = (fac.value).map(v => v.trim()).join(', ');
|
||||
copy.value = copy.value.map(v => v !== null ? abbreviateNumber(new Decimal(v.toFixed(2))) : null);
|
||||
copy.value = (copy.value).map(v => v.trim()).join(', ');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return fac;
|
||||
return copy;
|
||||
});
|
||||
c.attributes.forEach(att => {
|
||||
switch (att.type) {
|
||||
const attributes = c.attributes.map(att => {
|
||||
const copy = { ...att };
|
||||
switch (copy.type) {
|
||||
case 'date':
|
||||
att.value = att.value !== null ? moment(att.value).format('YYYY/MM/DD HH:mm:ss') : null;
|
||||
copy.value = copy.value !== null ? moment(copy.value).format('YYYY/MM/DD HH:mm:ss') : null;
|
||||
break;
|
||||
case 'float':
|
||||
att.value = att.value !== null ? new Decimal(att.value).toFixed(2) : null;
|
||||
copy.value = copy.value !== null ? new Decimal(copy.value).toFixed(2) : null;
|
||||
break
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return att;
|
||||
return copy;
|
||||
});
|
||||
const { facets, attributes, ...rest } = c;
|
||||
return { ...rest, facets, attributes };
|
||||
return {
|
||||
...c,
|
||||
started_at: moment(c.started_at).format('YYYY/MM/DD HH:mm'),
|
||||
completed_at: moment(c.completed_at).format('YYYY/MM/DD HH:mm'),
|
||||
facets,
|
||||
attributes,
|
||||
};
|
||||
});
|
||||
return newData
|
||||
};
|
||||
},
|
||||
loopTraces: state => {
|
||||
@@ -205,25 +209,28 @@ export const useConformanceStore = defineStore('conformanceStore', {
|
||||
},
|
||||
loopCases: state => {
|
||||
if(state.allLoopCases !== null){
|
||||
const newData = state.allLoopCases.map(c => {
|
||||
c.started_at = moment(c.started_at).format('YYYY/MM/DD HH:mm');
|
||||
c.completed_at = moment(c.completed_at).format('YYYY/MM/DD HH:mm');
|
||||
c.attributes.forEach(att => {
|
||||
switch (att.type) {
|
||||
return state.allLoopCases.map(c => {
|
||||
const attributes = c.attributes.map(att => {
|
||||
const copy = { ...att };
|
||||
switch (copy.type) {
|
||||
case 'date':
|
||||
att.value = att.value !== null ? moment(att.value).format('YYYY/MM/DD HH:mm:ss') : null;
|
||||
copy.value = copy.value !== null ? moment(copy.value).format('YYYY/MM/DD HH:mm:ss') : null;
|
||||
break;
|
||||
case 'float':
|
||||
att.value = att.value !== null ? new Decimal(att.value).toFixed(2) : null;
|
||||
copy.value = copy.value !== null ? new Decimal(copy.value).toFixed(2) : null;
|
||||
break
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return att;
|
||||
return copy;
|
||||
});
|
||||
return c;
|
||||
return {
|
||||
...c,
|
||||
started_at: moment(c.started_at).format('YYYY/MM/DD HH:mm'),
|
||||
completed_at: moment(c.completed_at).format('YYYY/MM/DD HH:mm'),
|
||||
attributes,
|
||||
};
|
||||
});
|
||||
return newData;
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
@@ -237,5 +237,28 @@ describe('allMapDataStore', () => {
|
||||
store.allBaseCase = [{ id: 1 }];
|
||||
expect(store.BaseInfiniteFirstCases).toBeUndefined();
|
||||
});
|
||||
|
||||
it('filterAttrs getter does not corrupt original state on repeated access', () => {
|
||||
const originalDate = '2023-06-15T10:30:00Z';
|
||||
store.allFilterAttrs = [
|
||||
{ type: 'date', min: originalDate, max: '2023-12-31T23:59:00Z' },
|
||||
];
|
||||
// Access the getter once
|
||||
store.filterAttrs;
|
||||
// The original state should still contain the ISO date, not a formatted string
|
||||
expect(store.allFilterAttrs[0].min).toBe(originalDate);
|
||||
});
|
||||
|
||||
it('filterAttrs getter returns consistent float values on repeated access', () => {
|
||||
store.allFilterAttrs = [
|
||||
{ type: 'float', min: 1.239, max: 5.671 },
|
||||
];
|
||||
const first = store.filterAttrs;
|
||||
const second = store.filterAttrs;
|
||||
// min rounds down (ROUND_DOWN=1), max rounds up (ROUND_UP=0)
|
||||
// Both accesses should produce the same result
|
||||
expect(first[0].min).toBe(second[0].min);
|
||||
expect(first[0].max).toBe(second[0].max);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -196,5 +196,18 @@ describe('conformanceStore', () => {
|
||||
// The date attribute should show minutes (30), not month (06)
|
||||
expect(result[0].attributes[0].value).toMatch(/:30:/);
|
||||
});
|
||||
|
||||
it('cases getter does not corrupt original state on repeated access', () => {
|
||||
const originalDate = '2023-06-15T10:30:00Z';
|
||||
store.allCases = [{
|
||||
started_at: originalDate,
|
||||
completed_at: '2023-06-15T11:45:00Z',
|
||||
facets: [],
|
||||
attributes: [],
|
||||
}];
|
||||
store.cases;
|
||||
// Original state should still contain the ISO date
|
||||
expect(store.allCases[0].started_at).toBe(originalDate);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user