config-manager.test.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /// <reference types="bun-types" />
  2. import { describe, expect, test } from 'bun:test';
  3. import { stripJsonComments } from './config-manager';
  4. describe('config-manager (barrel)', () => {
  5. describe('stripJsonComments', () => {
  6. test('returns unchanged JSON without comments', () => {
  7. const json = '{"key": "value"}';
  8. expect(stripJsonComments(json)).toBe(json);
  9. });
  10. test('strips single-line comments', () => {
  11. const json = `{
  12. "key": "value" // this is a comment
  13. }`;
  14. expect(JSON.parse(stripJsonComments(json))).toEqual({ key: 'value' });
  15. });
  16. test('strips multi-line comments', () => {
  17. const json = `{
  18. /* this is a
  19. multi-line comment */
  20. "key": "value"
  21. }`;
  22. expect(JSON.parse(stripJsonComments(json))).toEqual({ key: 'value' });
  23. });
  24. test('strips trailing commas', () => {
  25. const json = `{
  26. "key": "value",
  27. }`;
  28. expect(JSON.parse(stripJsonComments(json))).toEqual({ key: 'value' });
  29. });
  30. test('strips trailing commas in arrays', () => {
  31. const json = `{
  32. "arr": [1, 2, 3,]
  33. }`;
  34. expect(JSON.parse(stripJsonComments(json))).toEqual({ arr: [1, 2, 3] });
  35. });
  36. test('preserves URLs with double slashes', () => {
  37. const json = '{"url": "https://example.com"}';
  38. expect(JSON.parse(stripJsonComments(json))).toEqual({
  39. url: 'https://example.com',
  40. });
  41. });
  42. test('preserves strings containing comment-like patterns', () => {
  43. const json = '{"code": "// not a comment", "block": "/* also not */"}';
  44. expect(JSON.parse(stripJsonComments(json))).toEqual({
  45. code: '// not a comment',
  46. block: '/* also not */',
  47. });
  48. });
  49. test('handles complex JSONC with mixed comments and trailing commas', () => {
  50. const json = `{
  51. // Configuration for the plugin
  52. "plugin": ["oh-my-opencode-slim"],
  53. /* Provider settings
  54. with multiple lines */
  55. "provider": {
  56. "google": {
  57. "name": "Google", // inline comment
  58. },
  59. },
  60. }`;
  61. const result = JSON.parse(stripJsonComments(json));
  62. expect(result).toEqual({
  63. plugin: ['oh-my-opencode-slim'],
  64. provider: {
  65. google: {
  66. name: 'Google',
  67. },
  68. },
  69. });
  70. });
  71. test('handles escaped quotes in strings', () => {
  72. const json = '{"message": "He said \\"hello\\""}';
  73. expect(JSON.parse(stripJsonComments(json))).toEqual({
  74. message: 'He said "hello"',
  75. });
  76. });
  77. test('handles empty input', () => {
  78. expect(stripJsonComments('')).toBe('');
  79. });
  80. test('handles whitespace-only input', () => {
  81. expect(stripJsonComments(' ')).toBe(' ');
  82. });
  83. test('handles single-line comment at start of file', () => {
  84. const json = `// comment at start
  85. {"key": "value"}`;
  86. expect(JSON.parse(stripJsonComments(json))).toEqual({ key: 'value' });
  87. });
  88. test('handles comment-only lines between properties', () => {
  89. const json = `{
  90. "a": 1,
  91. // comment line
  92. "b": 2
  93. }`;
  94. expect(JSON.parse(stripJsonComments(json))).toEqual({ a: 1, b: 2 });
  95. });
  96. test('handles multiple trailing commas in nested structures', () => {
  97. const json = `{"nested": {"a": 1,},}`;
  98. expect(JSON.parse(stripJsonComments(json))).toEqual({ nested: { a: 1 } });
  99. });
  100. test('handles unclosed string gracefully without throwing', () => {
  101. const json = '{"key": "unclosed';
  102. expect(() => stripJsonComments(json)).not.toThrow();
  103. });
  104. test('preserves comma-bracket patterns inside strings', () => {
  105. const json = '{"script": "test [,]", "json": "{,}"}';
  106. const result = JSON.parse(stripJsonComments(json));
  107. expect(result.script).toBe('test [,]');
  108. expect(result.json).toBe('{,}');
  109. });
  110. test('preserves comma-brace patterns inside strings', () => {
  111. const json = '{"glob": "*.{js,ts}", "arr": "[a,]"}';
  112. const result = JSON.parse(stripJsonComments(json));
  113. expect(result.glob).toBe('*.{js,ts}');
  114. expect(result.arr).toBe('[a,]');
  115. });
  116. test('handles Windows CRLF line endings', () => {
  117. const json = '{\r\n "key": "value", // comment\r\n}';
  118. const result = JSON.parse(stripJsonComments(json));
  119. expect(result).toEqual({ key: 'value' });
  120. });
  121. });
  122. });