system-collapse.test.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { describe, expect, test } from 'bun:test';
  2. import { collapseSystemInPlace } from './system-collapse';
  3. /**
  4. * Regression tests for the system message collapse logic.
  5. *
  6. * PR #336's collapse was a silent no-op because it reassigned
  7. * output.system to a new array, but OpenCode core reads from the
  8. * original array reference. The fix mutates in-place.
  9. *
  10. * These tests import the actual shared function used by the hook,
  11. * so any regression in the implementation is caught immediately.
  12. */
  13. describe('collapseSystemInPlace', () => {
  14. test('mutates multi-element array in-place', () => {
  15. const system = ['part one', 'part two'];
  16. const output = { system };
  17. collapseSystemInPlace(output.system);
  18. // Same reference — callers holding the original array see the change
  19. expect(output.system).toBe(system);
  20. expect(system).toHaveLength(1);
  21. expect(system[0]).toBe('part one\n\npart two');
  22. });
  23. test('mutates three-element array in-place', () => {
  24. const system = ['header', 'todo reminder', 'file nudge'];
  25. const output = { system };
  26. collapseSystemInPlace(output.system);
  27. expect(output.system).toBe(system);
  28. expect(system).toHaveLength(1);
  29. expect(system[0]).toBe('header\n\ntodo reminder\n\nfile nudge');
  30. });
  31. test('handles single-element array', () => {
  32. const system = ['only element'];
  33. const output = { system };
  34. collapseSystemInPlace(output.system);
  35. expect(output.system).toBe(system);
  36. expect(system).toHaveLength(1);
  37. expect(system[0]).toBe('only element');
  38. });
  39. test('handles empty array', () => {
  40. const system: string[] = [];
  41. const output = { system };
  42. collapseSystemInPlace(output.system);
  43. expect(output.system).toBe(system);
  44. expect(system).toHaveLength(0);
  45. });
  46. test('preserves previous empty-string cleanup behavior', () => {
  47. const system = [''];
  48. const output = { system };
  49. collapseSystemInPlace(output.system);
  50. expect(output.system).toBe(system);
  51. expect(system).toHaveLength(0);
  52. });
  53. test('reassignment would NOT be visible (regression guard)', () => {
  54. // This test documents WHY we mutate in-place and not via reassignment.
  55. // Simulating the broken PR #336 approach to prove it fails.
  56. const system = ['a', 'b'];
  57. const output = { system };
  58. // Broken approach: reassign the property
  59. output.system = [output.system.join('\n\n')];
  60. // The output object sees the new array...
  61. expect(output.system).toEqual(['a\n\nb']);
  62. // ...but the original reference is untouched — this is the bug.
  63. expect(system).toEqual(['a', 'b']);
  64. expect(system).not.toBe(output.system);
  65. });
  66. });