|
| 1 | +import { describe, it, expect } from 'vitest'; |
| 2 | + |
| 3 | +import { parseLogLine } from '@/pages/index/logParse'; |
| 4 | + |
| 5 | +// Fixtures are real lines captured from `journalctl -u x-ui` on a production |
| 6 | +// host (the SysLog view) plus the in-memory app-log format. Each journald entry |
| 7 | +// carries a "Mon DD HH:MM:SS host ident[pid]: " prefix that the viewer used to |
| 8 | +// mistake for the level, leaving only a bare timestamp on screen. |
| 9 | +describe('parseLogLine — SysLog (journalctl) formats', () => { |
| 10 | + it('x-ui go-logging line: keeps level, strips prefix, tags X-UI', () => { |
| 11 | + const r = parseLogLine( |
| 12 | + 'Jun 08 23:57:28 ubuntu-4gb-fsn1-1 /usr/local/x-ui/x-ui[72297]: INFO - mtproto: started mtg for inbound 3 on 0.0.0.0:8443', |
| 13 | + ); |
| 14 | + expect(r.stamp).toBe('Jun 08 23:57:28'); |
| 15 | + expect(r.levelText).toBe('INFO'); |
| 16 | + expect(r.service).toBe('X-UI:'); |
| 17 | + expect(r.body).toBe('mtproto: started mtg for inbound 3 on 0.0.0.0:8443'); |
| 18 | + }); |
| 19 | + |
| 20 | + it('xray go-logging line: lifts the XRAY service tag', () => { |
| 21 | + const r = parseLogLine( |
| 22 | + 'Jun 08 23:56:52 ubuntu-4gb-fsn1-1 /usr/local/x-ui/x-ui[72297]: WARNING - XRAY: core: Xray 26.6.1 started', |
| 23 | + ); |
| 24 | + expect(r.stamp).toBe('Jun 08 23:56:52'); |
| 25 | + expect(r.levelText).toBe('WARNING'); |
| 26 | + expect(r.service).toBe('XRAY:'); |
| 27 | + expect(r.body).toBe('core: Xray 26.6.1 started'); |
| 28 | + }); |
| 29 | + |
| 30 | + it('Go std-log line: strips the redundant embedded date, keeps the message', () => { |
| 31 | + const r = parseLogLine( |
| 32 | + 'Jun 08 19:22:22 ubuntu-4gb-fsn1-1 x-ui[1439]: 2026/06/08 19:22:22 http: TLS handshake error from 18.97.5.1:36022: EOF', |
| 33 | + ); |
| 34 | + expect(r.stamp).toBe('Jun 08 19:22:22'); |
| 35 | + expect(r.levelText).toBe(''); |
| 36 | + expect(r.body).toBe('http: TLS handshake error from 18.97.5.1:36022: EOF'); |
| 37 | + }); |
| 38 | + |
| 39 | + it('telego bracketed line: lifts the ERROR level out of "[ts] ERROR ..."', () => { |
| 40 | + const r = parseLogLine( |
| 41 | + 'Jun 09 00:14:52 ubuntu-4gb-fsn1-1 x-ui[72297]: [Tue Jun 9 00:14:52 UTC 2026] ERROR Retrying getting updates in 8s...', |
| 42 | + ); |
| 43 | + expect(r.stamp).toBe('Jun 09 00:14:52'); |
| 44 | + expect(r.levelText).toBe('ERROR'); |
| 45 | + expect(r.body).toBe('Retrying getting updates in 8s...'); |
| 46 | + }); |
| 47 | + |
| 48 | + it('systemd line: shows the body rather than a bare timestamp', () => { |
| 49 | + const r = parseLogLine( |
| 50 | + 'Jun 08 23:56:47 ubuntu-4gb-fsn1-1 systemd[1]: Stopping x-ui.service - x-ui Service...', |
| 51 | + ); |
| 52 | + expect(r.stamp).toBe('Jun 08 23:56:47'); |
| 53 | + expect(r.body).toBe('Stopping x-ui.service - x-ui Service...'); |
| 54 | + }); |
| 55 | + |
| 56 | + it('never collapses a journald entry to just its timestamp', () => { |
| 57 | + const r = parseLogLine( |
| 58 | + 'Jun 09 00:15:00 ubuntu-4gb-fsn1-1 x-ui[72297]: [Tue Jun 9 00:15:00 UTC 2026] ERROR Getting updates: telego: getUpdates: api: 409 "Conflict"', |
| 59 | + ); |
| 60 | + expect(r.body.length).toBeGreaterThan(0); |
| 61 | + expect(r.body).toContain('Conflict'); |
| 62 | + }); |
| 63 | +}); |
| 64 | + |
| 65 | +describe('parseLogLine — app-log format (SysLog off)', () => { |
| 66 | + it('parses "YYYY/MM/DD HH:MM:SS LEVEL - body"', () => { |
| 67 | + const r = parseLogLine('2026/06/09 00:35:09 INFO - mtproto: started mtg for inbound 3 on 0.0.0.0:8443'); |
| 68 | + expect(r.date).toBe('2026/06/09'); |
| 69 | + expect(r.time).toBe('00:35:09'); |
| 70 | + expect(r.levelText).toBe('INFO'); |
| 71 | + expect(r.service).toBe('X-UI:'); |
| 72 | + expect(r.body).toBe('mtproto: started mtg for inbound 3 on 0.0.0.0:8443'); |
| 73 | + }); |
| 74 | + |
| 75 | + it('handles an empty line without throwing', () => { |
| 76 | + const r = parseLogLine(''); |
| 77 | + expect(r.stamp).toBe(''); |
| 78 | + expect(r.body).toBe(''); |
| 79 | + }); |
| 80 | +}); |
0 commit comments