mtg-playerinfo 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,29 +15,75 @@ test('UntappedFetcher: parses most recent match and extracts MTGA rank', () => {
15
15
  const matches = JSON.parse(fixtureJson)
16
16
 
17
17
  const url = 'https://mtga.untapped.gg/profile/7de50700-c3f6-48e4-a38d-2add5b0d9b71/76DCDWCZS5FX5PIEEMUVY6GV74'
18
- const result = fetcher.parseMatch(matches[0], url)
18
+ const result = fetcher.parseMatches(matches, url)
19
19
 
20
20
  assert.strictEqual(result.source, 'Untapped.gg')
21
21
  assert.strictEqual(result.url, url)
22
22
 
23
- assert.match(result.mtga_rank, /^(Bronze|Silver|Gold|Platinum|Diamond|Mythic)\s\d+$/)
23
+ assert.strictEqual(typeof result.mtga_rank, 'object')
24
+
25
+ // Format is either "Rank Tier" (e.g. "Diamond 2") or "Mythic #Place" (e.g. "Mythic #123")
26
+ if (result.mtga_rank.constructed !== undefined) {
27
+ assert.match(result.mtga_rank.constructed, /^(Bronze|Silver|Gold|Platinum|Diamond|Mythic)(\s\d+|\s#\d+)$/)
28
+ }
29
+ if (result.mtga_rank.limited !== undefined) {
30
+ assert.match(result.mtga_rank.limited, /^(Bronze|Silver|Gold|Platinum|Diamond|Mythic)(\s\d+|\s#\d+)$/)
31
+ }
24
32
  })
25
33
 
26
34
  test('UntappedFetcher: handles missing rank data', () => {
27
35
  const fetcher = new UntappedFetcher()
28
- const testMatch = {
29
- friendly_ranking_class_after: null,
30
- friendly_ranking_tier_after: null
31
- }
36
+ const testMatches = [
37
+ {
38
+ super_format: 2,
39
+ friendly_ranking_class_after: null,
40
+ friendly_ranking_tier_after: null,
41
+ match_start: 1000
42
+ },
43
+ {
44
+ super_format: 1,
45
+ friendly_ranking_class_after: null,
46
+ friendly_ranking_tier_after: null,
47
+ match_start: 2000
48
+ }
49
+ ]
32
50
 
33
51
  const url = 'https://mtga.untapped.gg/profile/test-user/test-code'
34
- const result = fetcher.parseMatch(testMatch, url)
52
+ const result = fetcher.parseMatches(testMatches, url)
35
53
 
36
- assert.strictEqual(result.mtga_rank, null)
54
+ assert.strictEqual('constructed' in result.mtga_rank, false)
55
+ assert.strictEqual('limited' in result.mtga_rank, false)
37
56
  })
38
57
 
39
- test('UntappedFetcher: constructs correct API URL from two-part ID', () => {
58
+ test('UntappedFetcher: formats Mythic rank with leaderboard place or percentile', () => {
40
59
  const fetcher = new UntappedFetcher()
60
+ const testMatches = [
61
+ {
62
+ super_format: 2,
63
+ friendly_ranking_class_after: 'Mythic',
64
+ friendly_ranking_tier_after: null,
65
+ friendly_mythic_leaderboard_place_after: 123,
66
+ friendly_mythic_percentile_after: 101.5,
67
+ match_start: 1000
68
+ },
69
+ {
70
+ super_format: 1,
71
+ friendly_ranking_class_after: 'Mythic',
72
+ friendly_ranking_tier_after: null,
73
+ friendly_mythic_leaderboard_place_after: null,
74
+ friendly_mythic_percentile_after: 98.789,
75
+ match_start: 2000
76
+ }
77
+ ]
78
+
79
+ const url = 'https://mtga.untapped.gg/profile/test-user/test-code'
80
+ const result = fetcher.parseMatches(testMatches, url)
81
+
82
+ assert.strictEqual(result.mtga_rank.constructed, 'Mythic #123')
83
+ assert.strictEqual(result.mtga_rank.limited, 'Mythic 98%')
84
+ })
85
+
86
+ test('UntappedFetcher: constructs correct API URL from two-part ID', () => {
41
87
  const userId = '7de50700-c3f6-48e4-a38d-2add5b0d9b71'
42
88
  const playerCode = '76DCDWCZS5FX5PIEEMUVY6GV74'
43
89
  const id = `${userId}/${playerCode}`
@@ -53,6 +99,3 @@ test('UntappedFetcher: constructs correct API URL from two-part ID', () => {
53
99
  const profileUrl = `https://mtga.untapped.gg/profile/${parts[0]}/${parts[1]}`
54
100
  assert.strictEqual(profileUrl, 'https://mtga.untapped.gg/profile/7de50700-c3f6-48e4-a38d-2add5b0d9b71/76DCDWCZS5FX5PIEEMUVY6GV74')
55
101
  })
56
-
57
-
58
-
@@ -13,7 +13,7 @@ test('PlayerInfoManager: verbose mode logs promoted properties', async () => {
13
13
  }
14
14
  ]
15
15
 
16
- let capturedLogs = []
16
+ const capturedLogs = []
17
17
  const originalLog = console.log
18
18
  console.log = (msg) => { capturedLogs.push(msg) }
19
19
 
@@ -45,12 +45,12 @@ test('PlayerInfoManager: verbose mode logs matching property values', async () =
45
45
  }
46
46
  ]
47
47
 
48
- let capturedLogs = []
48
+ const capturedLogs = []
49
49
  const originalLog = console.log
50
50
  console.log = (msg) => { capturedLogs.push(msg) }
51
51
 
52
52
  try {
53
- const merged = manager.mergeData(results, true)
53
+ manager.mergeData(results, true)
54
54
  assert.ok(capturedLogs.some(log => log.includes('🆗') && log.includes('name') && log.includes('Source2')),
55
55
  'Should log matching property with 🆗 emoji')
56
56
  assert.ok(capturedLogs.some(log => log.includes('🆗') && log.includes('team') && log.includes('Source2')),
@@ -76,7 +76,7 @@ test('PlayerInfoManager: verbose mode logs conflicting property values', async (
76
76
  }
77
77
  ]
78
78
 
79
- let capturedLogs = []
79
+ const capturedLogs = []
80
80
  const originalLog = console.log
81
81
  console.log = (msg) => { capturedLogs.push(msg) }
82
82
 
@@ -108,12 +108,12 @@ test('PlayerInfoManager: verbose mode uses photo emoji for photo conflicts', asy
108
108
  }
109
109
  ]
110
110
 
111
- let capturedLogs = []
111
+ const capturedLogs = []
112
112
  const originalLog = console.log
113
113
  console.log = (msg) => { capturedLogs.push(msg) }
114
114
 
115
115
  try {
116
- const merged = manager.mergeData(results, true)
116
+ manager.mergeData(results, true)
117
117
  assert.ok(capturedLogs.some(log => log.includes('🆕') && log.includes('photo')),
118
118
  'Should log photo conflict with 🆕 emoji instead of 🆚')
119
119
  } finally {
@@ -141,12 +141,12 @@ test('PlayerInfoManager: verbose mode logs with null/undefined properties', asyn
141
141
  }
142
142
  ]
143
143
 
144
- let capturedLogs = []
144
+ const capturedLogs = []
145
145
  const originalLog = console.log
146
146
  console.log = (msg) => { capturedLogs.push(msg) }
147
147
 
148
148
  try {
149
- const merged = manager.mergeData(results, true)
149
+ manager.mergeData(results, true)
150
150
  assert.ok(capturedLogs.some(log => log.includes('⬆️') && log.includes('bio') && log.includes('Source2')),
151
151
  'Should promote bio from Source2 after Source1 had null')
152
152
  assert.ok(capturedLogs.some(log => log.includes('⬆️') && log.includes('team') && log.includes('Source2')),
@@ -167,12 +167,12 @@ test('PlayerInfoManager: verbose mode is false by default and logs nothing', asy
167
167
  }
168
168
  ]
169
169
 
170
- let capturedLogs = []
170
+ const capturedLogs = []
171
171
  const originalLog = console.log
172
172
  console.log = (msg) => { capturedLogs.push(msg) }
173
173
 
174
174
  try {
175
- const merged = manager.mergeData(results, false)
175
+ manager.mergeData(results, false)
176
176
  assert.equal(capturedLogs.length, 0, 'Should not log when verbose is false')
177
177
  } finally {
178
178
  console.log = originalLog
@@ -194,13 +194,12 @@ test('PlayerInfoManager: verbose mode logs each property separately', async () =
194
194
  }
195
195
  ]
196
196
 
197
- let capturedLogs = []
197
+ const capturedLogs = []
198
198
  const originalLog = console.log
199
199
  console.log = (msg) => { capturedLogs.push(msg) }
200
200
 
201
201
  try {
202
- const merged = manager.mergeData(results, true)
203
- // Should have multiple promoted property logs
202
+ manager.mergeData(results, true)
204
203
  const promotedLogs = capturedLogs.filter(log => log.includes('⬆️'))
205
204
  assert.ok(promotedLogs.length >= 5, `Should log 5+ promoted properties, got ${promotedLogs.length}`)
206
205
  assert.ok(promotedLogs.some(log => log.includes('name')))
@@ -212,4 +211,3 @@ test('PlayerInfoManager: verbose mode logs each property separately', async () =
212
211
  console.log = originalLog
213
212
  }
214
213
  })
215
-