Skip to content

Commit 67bfe32

Browse files
committed
Add join JSON
1 parent 95d06cb commit 67bfe32

File tree

5 files changed

+164
-44
lines changed

5 files changed

+164
-44
lines changed

Core/Tests/ServiceTests/Environment.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ func completion(text: String, range: CursorRange, uuid: String = "") -> CodeSugg
1414
}
1515

1616
class MockSuggestionService: GitHubCopilotSuggestionServiceType {
17+
func cancelOngoingTask(workDoneToken: String) async {
18+
fatalError()
19+
}
20+
1721
func notifyChangeTextDocument(fileURL: URL, content: String, version: Int) async throws {
1822
fatalError()
1923
}

TestPlan.xctestplan

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,135 +24,135 @@
2424
"testTargets" : [
2525
{
2626
"target" : {
27-
"containerPath" : "container:Core",
28-
"identifier" : "ServiceTests",
29-
"name" : "ServiceTests"
27+
"containerPath" : "container:Tool",
28+
"identifier" : "OpenAIServiceTests",
29+
"name" : "OpenAIServiceTests"
3030
}
3131
},
3232
{
3333
"target" : {
3434
"containerPath" : "container:Core",
35-
"identifier" : "SuggestionWidgetTests",
36-
"name" : "SuggestionWidgetTests"
35+
"identifier" : "KeyBindingManagerTests",
36+
"name" : "KeyBindingManagerTests"
3737
}
3838
},
3939
{
4040
"target" : {
41-
"containerPath" : "container:Core",
42-
"identifier" : "PromptToCodeServiceTests",
43-
"name" : "PromptToCodeServiceTests"
41+
"containerPath" : "container:Tool",
42+
"identifier" : "SuggestionInjectorTests",
43+
"name" : "SuggestionInjectorTests"
4444
}
4545
},
4646
{
4747
"target" : {
4848
"containerPath" : "container:Tool",
49-
"identifier" : "LangChainTests",
50-
"name" : "LangChainTests"
49+
"identifier" : "SharedUIComponentsTests",
50+
"name" : "SharedUIComponentsTests"
5151
}
5252
},
5353
{
5454
"target" : {
5555
"containerPath" : "container:Tool",
56-
"identifier" : "OpenAIServiceTests",
57-
"name" : "OpenAIServiceTests"
56+
"identifier" : "SuggestionBasicTests",
57+
"name" : "SuggestionBasicTests"
5858
}
5959
},
6060
{
6161
"target" : {
6262
"containerPath" : "container:Core",
63-
"identifier" : "ChatServiceTests",
64-
"name" : "ChatServiceTests"
63+
"identifier" : "PromptToCodeServiceTests",
64+
"name" : "PromptToCodeServiceTests"
6565
}
6666
},
6767
{
6868
"target" : {
6969
"containerPath" : "container:Tool",
70-
"identifier" : "TokenEncoderTests",
71-
"name" : "TokenEncoderTests"
70+
"identifier" : "JoinJSONTests",
71+
"name" : "JoinJSONTests"
7272
}
7373
},
7474
{
7575
"target" : {
7676
"containerPath" : "container:Tool",
77-
"identifier" : "SharedUIComponentsTests",
78-
"name" : "SharedUIComponentsTests"
77+
"identifier" : "FocusedCodeFinderTests",
78+
"name" : "FocusedCodeFinderTests"
7979
}
8080
},
8181
{
8282
"target" : {
8383
"containerPath" : "container:Tool",
84-
"identifier" : "ASTParserTests",
85-
"name" : "ASTParserTests"
84+
"identifier" : "ActiveDocumentChatContextCollectorTests",
85+
"name" : "ActiveDocumentChatContextCollectorTests"
8686
}
8787
},
8888
{
8989
"target" : {
90-
"containerPath" : "container:Core",
91-
"identifier" : "ServiceUpdateMigrationTests",
92-
"name" : "ServiceUpdateMigrationTests"
90+
"containerPath" : "container:Tool",
91+
"identifier" : "XcodeInspectorTests",
92+
"name" : "XcodeInspectorTests"
9393
}
9494
},
9595
{
9696
"target" : {
9797
"containerPath" : "container:Tool",
98-
"identifier" : "KeychainTests",
99-
"name" : "KeychainTests"
98+
"identifier" : "GitHubCopilotServiceTests",
99+
"name" : "GitHubCopilotServiceTests"
100100
}
101101
},
102102
{
103103
"target" : {
104-
"containerPath" : "container:Tool",
105-
"identifier" : "ActiveDocumentChatContextCollectorTests",
106-
"name" : "ActiveDocumentChatContextCollectorTests"
104+
"containerPath" : "container:Core",
105+
"identifier" : "SuggestionWidgetTests",
106+
"name" : "SuggestionWidgetTests"
107107
}
108108
},
109109
{
110110
"target" : {
111111
"containerPath" : "container:Tool",
112-
"identifier" : "GitHubCopilotServiceTests",
113-
"name" : "GitHubCopilotServiceTests"
112+
"identifier" : "TokenEncoderTests",
113+
"name" : "TokenEncoderTests"
114114
}
115115
},
116116
{
117117
"target" : {
118-
"containerPath" : "container:Tool",
119-
"identifier" : "FocusedCodeFinderTests",
120-
"name" : "FocusedCodeFinderTests"
118+
"containerPath" : "container:Core",
119+
"identifier" : "ChatServiceTests",
120+
"name" : "ChatServiceTests"
121121
}
122122
},
123123
{
124124
"target" : {
125125
"containerPath" : "container:Tool",
126-
"identifier" : "XcodeInspectorTests",
127-
"name" : "XcodeInspectorTests"
126+
"identifier" : "LangChainTests",
127+
"name" : "LangChainTests"
128128
}
129129
},
130130
{
131131
"target" : {
132132
"containerPath" : "container:Tool",
133-
"identifier" : "SuggestionProviderTests",
134-
"name" : "SuggestionProviderTests"
133+
"identifier" : "KeychainTests",
134+
"name" : "KeychainTests"
135135
}
136136
},
137137
{
138138
"target" : {
139139
"containerPath" : "container:Core",
140-
"identifier" : "KeyBindingManagerTests",
141-
"name" : "KeyBindingManagerTests"
140+
"identifier" : "ServiceTests",
141+
"name" : "ServiceTests"
142142
}
143143
},
144144
{
145145
"target" : {
146146
"containerPath" : "container:Tool",
147-
"identifier" : "SuggestionBasicTests",
148-
"name" : "SuggestionBasicTests"
147+
"identifier" : "ASTParserTests",
148+
"name" : "ASTParserTests"
149149
}
150150
},
151151
{
152152
"target" : {
153153
"containerPath" : "container:Tool",
154-
"identifier" : "SuggestionInjectorTests",
155-
"name" : "SuggestionInjectorTests"
154+
"identifier" : "SuggestionProviderTests",
155+
"name" : "SuggestionProviderTests"
156156
}
157157
},
158158
{
@@ -161,6 +161,13 @@
161161
"identifier" : "CodeDiffTests",
162162
"name" : "CodeDiffTests"
163163
}
164+
},
165+
{
166+
"target" : {
167+
"containerPath" : "container:Core",
168+
"identifier" : "ServiceUpdateMigrationTests",
169+
"name" : "ServiceUpdateMigrationTests"
170+
}
164171
}
165172
],
166173
"version" : 1

Tool/Package.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ let package = Package(
8181
url: "https://github.com/intitni/generative-ai-swift",
8282
branch: "support-setting-base-url"
8383
),
84-
.package(url: "https://github.com/intitni/CopilotForXcodeKit", branch: "feature/custom-chat-tab"),
84+
.package(
85+
url: "https://github.com/intitni/CopilotForXcodeKit",
86+
branch: "feature/custom-chat-tab"
87+
),
8588

8689
// TreeSitter
8790
.package(url: "https://github.com/intitni/SwiftTreeSitter.git", branch: "main"),
@@ -104,6 +107,9 @@ let package = Package(
104107

105108
.target(name: "ObjectiveCExceptionHandling"),
106109

110+
.target(name: "JoinJSON"),
111+
.testTarget(name: "JoinJSONTests", dependencies: ["JoinJSON"]),
112+
107113
.target(name: "CodeDiff", dependencies: ["SuggestionBasic"]),
108114
.testTarget(name: "CodeDiffTests", dependencies: ["CodeDiff"]),
109115

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Foundation
2+
3+
public struct JoinJSON {
4+
public init() {}
5+
6+
public func join(_ a: String, with b: String) -> Data {
7+
return join(a.data(using: .utf8) ?? Data(), with: b.data(using: .utf8) ?? Data())
8+
}
9+
10+
public func join(_ a: Data, with b: String) -> Data {
11+
return join(a, with: b.data(using: .utf8) ?? Data())
12+
}
13+
14+
public func join(_ a: Data, with b: Data) -> Data {
15+
guard let firstDict = try? JSONSerialization.jsonObject(with: a) as? [String: Any],
16+
let secondDict = try? JSONSerialization.jsonObject(with: b) as? [String: Any]
17+
else {
18+
return a
19+
}
20+
21+
var merged = firstDict
22+
for (key, value) in secondDict {
23+
merged[key] = value
24+
}
25+
26+
return (try? JSONSerialization.data(withJSONObject: merged)) ?? a
27+
}
28+
}
29+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import Foundation
2+
3+
import XCTest
4+
@testable import JoinJSON
5+
6+
final class JoinJSONTests: XCTestCase {
7+
var sut: JoinJSON!
8+
9+
override func setUp() {
10+
super.setUp()
11+
sut = JoinJSON()
12+
}
13+
14+
override func tearDown() {
15+
sut = nil
16+
super.tearDown()
17+
}
18+
19+
func test_join_two_valid_json_strings() throws {
20+
let json1 = """
21+
{"name": "John"}
22+
"""
23+
let json2 = """
24+
{"age": 30}
25+
"""
26+
27+
let result = sut.join(json1, with: json2)
28+
let dict = try JSONSerialization.jsonObject(with: result) as? [String: Any]
29+
30+
XCTAssertEqual(dict?["name"] as? String, "John")
31+
XCTAssertEqual(dict?["age"] as? Int, 30)
32+
}
33+
34+
func test_join_with_invalid_json_returns_first_data() {
35+
let json1 = """
36+
{"name": "John"}
37+
"""
38+
let invalidJSON = "invalid json"
39+
40+
let result = sut.join(json1, with: invalidJSON)
41+
XCTAssertEqual(result, json1.data(using: .utf8))
42+
}
43+
44+
func test_join_with_overlapping_keys_prefers_second_value() throws {
45+
let json1 = """
46+
{"name": "John", "age": 25}
47+
"""
48+
let json2 = """
49+
{"age": 30}
50+
"""
51+
52+
let result = sut.join(json1, with: json2)
53+
let dict = try JSONSerialization.jsonObject(with: result) as? [String: Any]
54+
55+
XCTAssertEqual(dict?["name"] as? String, "John")
56+
XCTAssertEqual(dict?["age"] as? Int, 30)
57+
}
58+
59+
func test_join_with_data_input() throws {
60+
let data1 = """
61+
{"name": "John"}
62+
""".data(using: .utf8)!
63+
64+
let data2 = """
65+
{"age": 30}
66+
""".data(using: .utf8)!
67+
68+
let result = sut.join(data1, with: data2)
69+
let dict = try JSONSerialization.jsonObject(with: result) as? [String: Any]
70+
71+
XCTAssertEqual(dict?["name"] as? String, "John")
72+
XCTAssertEqual(dict?["age"] as? Int, 30)
73+
}
74+
}

0 commit comments

Comments
 (0)