Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: 1234567, downsampled: null},
});

openUpdateRetentionSettingsModal({
Expand All @@ -62,6 +63,7 @@ describe('UpdateRetentionSettingsModal', () => {
expect(getSpinbutton('Spans Downsampled')).toHaveValue(30);
expect(getSpinbutton('Logs Standard')).toHaveValue(45);
expect(getSpinbutton('Logs Downsampled')).toHaveValue(15);
expect(getSpinbutton('Org Retention')).toHaveValue(1234567);

expect(screen.getByRole('button', {name: 'Cancel'})).toBeInTheDocument();
expect(screen.getByRole('button', {name: 'Update Settings'})).toBeInTheDocument();
Expand Down Expand Up @@ -122,6 +124,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: null, downsampled: null},
});

openUpdateRetentionSettingsModal({
Expand All @@ -132,6 +135,7 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

expect(getSpinbutton('Org Retention')).toHaveValue(null);
expect(getSpinbutton('Spans Standard')).toHaveValue(90);
expect(getSpinbutton('Spans Downsampled')).toHaveValue(null);
expect(getSpinbutton('Logs Standard')).toHaveValue(30);
Expand All @@ -156,6 +160,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: 123, downsampled: null},
});

const updateMock = MockApiClient.addMockResponse({
Expand All @@ -172,6 +177,9 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

await userEvent.clear(getSpinbutton('Org Retention'));
await userEvent.type(getSpinbutton('Org Retention'), '456');

await userEvent.clear(getSpinbutton('Spans Standard'));
await userEvent.type(getSpinbutton('Spans Standard'), '120');

Expand All @@ -192,6 +200,10 @@ describe('UpdateRetentionSettingsModal', () => {
expect.objectContaining({
method: 'POST',
data: {
orgRetention: {
standard: 456,
downsampled: null,
},
retentions: {
spans: {
standard: 120,
Expand Down Expand Up @@ -228,6 +240,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am2_f'),
orgRetention: {standard: null, downsampled: null},
});

const updateMock = MockApiClient.addMockResponse({
Expand All @@ -244,6 +257,8 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

await userEvent.clear(getSpinbutton('Org Retention'));

await userEvent.clear(getSpinbutton('Transactions Standard'));
await userEvent.type(getSpinbutton('Transactions Standard'), '120');

Expand All @@ -264,6 +279,10 @@ describe('UpdateRetentionSettingsModal', () => {
expect.objectContaining({
method: 'POST',
data: {
orgRetention: {
standard: null,
downsampled: null,
},
retentions: {
transactions: {
standard: 120,
Expand Down Expand Up @@ -300,6 +319,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: 123, downsampled: null},
});

const updateMock = MockApiClient.addMockResponse({
Expand All @@ -316,6 +336,8 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

await userEvent.clear(getSpinbutton('Org Retention'));

await userEvent.clear(getSpinbutton('Spans Standard'));
await userEvent.type(getSpinbutton('Spans Standard'), '90');

Expand All @@ -334,6 +356,10 @@ describe('UpdateRetentionSettingsModal', () => {
expect.objectContaining({
method: 'POST',
data: {
orgRetention: {
standard: null,
downsampled: null,
},
retentions: {
spans: {
standard: 90,
Expand Down Expand Up @@ -370,6 +396,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: null, downsampled: null},
});

const updateMock = MockApiClient.addMockResponse({
Expand All @@ -386,6 +413,8 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

await userEvent.clear(getSpinbutton('Org Retention'));

await userEvent.clear(getSpinbutton('Spans Standard'));
await userEvent.type(getSpinbutton('Spans Standard'), '90');

Expand All @@ -406,6 +435,10 @@ describe('UpdateRetentionSettingsModal', () => {
expect.objectContaining({
method: 'POST',
data: {
orgRetention: {
standard: null,
downsampled: null,
},
retentions: {
spans: {
standard: 90,
Expand Down Expand Up @@ -442,6 +475,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: null, downsampled: null},
});

const updateMock = MockApiClient.addMockResponse({
Expand All @@ -458,6 +492,8 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

await userEvent.clear(getSpinbutton('Org Retention'));

await userEvent.clear(getSpinbutton('Spans Standard'));
await userEvent.type(getSpinbutton('Spans Standard'), '180');

Expand All @@ -472,6 +508,10 @@ describe('UpdateRetentionSettingsModal', () => {
expect.objectContaining({
method: 'POST',
data: {
orgRetention: {
standard: null,
downsampled: null,
},
retentions: {
spans: {
standard: 180,
Expand Down Expand Up @@ -506,6 +546,7 @@ describe('UpdateRetentionSettingsModal', () => {
}),
},
planDetails: PlanDetailsLookupFixture('am3_f'),
orgRetention: {standard: null, downsampled: null},
});

const updateMock = MockApiClient.addMockResponse({
Expand All @@ -522,6 +563,8 @@ describe('UpdateRetentionSettingsModal', () => {

await loadModal();

await userEvent.clear(getSpinbutton('Org Retention'));

await userEvent.clear(getSpinbutton('Logs Standard'));
await userEvent.type(getSpinbutton('Logs Standard'), '60');

Expand All @@ -536,6 +579,10 @@ describe('UpdateRetentionSettingsModal', () => {
expect.objectContaining({
method: 'POST',
data: {
orgRetention: {
standard: null,
downsampled: null,
},
retentions: {
spans: {
standard: 90,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ function UpdateRetentionSettingsModal({
}: ModalProps) {
const api = useApi();

const [orgStandard, setOrgStandard] = useState<number | null | string>(
subscription.orgRetention?.standard ?? null
);

const [logBytesStandard, setLogBytesStandard] = useState<number | null | string>(
subscription.categories.logBytes?.retention?.standard ?? null
);
Expand Down Expand Up @@ -78,7 +82,12 @@ function UpdateRetentionSettingsModal({
};
}

const data = {retentions};
const orgRetention = {
standard: orgStandard === null || orgStandard === '' ? null : Number(orgStandard),
downsampled: null,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Empty Field Values Mapped Inconsistently

The orgRetention.standard value is inconsistently handled when the field is cleared. If orgStandard is null (when the field starts empty and isn't modified), Number(null) converts it to 0 instead of null. If orgStandard is '' (when a filled field is cleared), it correctly becomes null. This creates different behavior for the same user action (clearing the field) based on the initial value, violating the expected semantics where empty fields should consistently map to null.

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is outdated.


const data = {retentions, orgRetention};

api.request(`/_admin/${organization.slug}/retention-settings/`, {
method: 'POST',
Expand Down Expand Up @@ -110,6 +119,12 @@ function UpdateRetentionSettingsModal({
</div>
<br />
<Form onSubmit={onSubmit} submitLabel="Update Settings" onCancel={closeModal}>
<NumberField
name="orgStandard"
label="Org Retention"
defaultValue={orgStandard}
onChange={setOrgStandard}
/>
{hasCategoryFeature(DataCategory.LOG_BYTE, subscription, organization) && (
<Fragment>
<NumberField
Expand Down
Loading