Skip to content

Commit 174630d

Browse files
authored
Merge pull request #21 from cybozu/add-fetch-fields-tests
Added FetchFieldsResponseTests & FetchRecordsResponseTests
2 parents f428510 + 5c309f5 commit 174630d

21 files changed

+2608
-74
lines changed

Example/Example/Extensions/KintoneAPI+Extension.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extension FieldProperty: @retroactive Identifiable {
1616
}
1717

1818
extension FieldOption: @retroactive Identifiable {
19-
public var id: String { index }
19+
public var id: Int { index }
2020
}
2121

2222
extension Entity.Read: @retroactive Identifiable {

Example/Example/FetchFields/FieldDetailView.swift

+20-9
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct FieldDetailView: View {
2727
CornerRadiusText("Expression: \(attribute.expression)")
2828
CornerRadiusText("Hide Expression: \(attribute.hideExpression)")
2929
CornerRadiusText("Format: \(attribute.format)")
30-
CornerRadiusText("Display Scale: \(attribute.displayScale)")
30+
CornerRadiusText("Display Scale: \(String(optional: attribute.displayScale))")
3131
CornerRadiusText("Unit: \(attribute.unit)")
3232
CornerRadiusText("Unit Position: \(attribute.unitPosition)")
3333

@@ -87,15 +87,15 @@ struct FieldDetailView: View {
8787
CornerRadiusText("No Label: \(attribute.noLabel)")
8888
CornerRadiusText("Required: \(attribute.required)")
8989
CornerRadiusText("Link Protocol: \(attribute.linkProtocol)")
90-
CornerRadiusText("Min Length: \(attribute.minLength)")
91-
CornerRadiusText("Max Length: \(attribute.maxLength)")
90+
CornerRadiusText("Min Length: \(String(optional: attribute.minLength))")
91+
CornerRadiusText("Max Length: \(String(optional: attribute.maxLength))")
9292
CornerRadiusText("Unique: \(attribute.unique)")
9393
CornerRadiusText("Default Value: \(attribute.defaultValue)")
9494

9595
case let .lookup(attribute):
9696
CornerRadiusText("No Label: \(attribute.noLabel)")
9797
CornerRadiusText("Required: \(attribute.required)")
98-
CornerRadiusText("Related App/App: \(attribute.lookup.relatedApp.app)")
98+
CornerRadiusText("Related App/App: \(attribute.lookup.relatedApp.appID)")
9999
CornerRadiusText("Related App/Code: \(attribute.lookup.relatedApp.code)")
100100
CornerRadiusText("Related Key Field: \(attribute.lookup.relatedKeyField)")
101101
FieldMappingsView(fieldMappings: attribute.lookup.fieldMappings)
@@ -120,12 +120,12 @@ struct FieldDetailView: View {
120120
case let .number(attribute):
121121
CornerRadiusText("No Label: \(attribute.noLabel)")
122122
CornerRadiusText("Required: \(attribute.required)")
123-
CornerRadiusText("Min Value: \(attribute.minValue)")
124-
CornerRadiusText("Max Value: \(attribute.maxValue)")
123+
CornerRadiusText("Min Value: \(String(optional: attribute.minValue))")
124+
CornerRadiusText("Max Value: \(String(optional: attribute.maxValue))")
125125
CornerRadiusText("Digit: \(attribute.digit)")
126126
CornerRadiusText("Unique: \(attribute.unique)")
127127
CornerRadiusText("Default Value: \(attribute.defaultValue)")
128-
CornerRadiusText("Display Scale: \(attribute.displayScale)")
128+
CornerRadiusText("Display Scale: \(String(optional: attribute.displayScale))")
129129
CornerRadiusText("Unit: \(attribute.unit)")
130130
CornerRadiusText("Unit Position: \(attribute.unitPosition)")
131131

@@ -145,6 +145,17 @@ struct FieldDetailView: View {
145145
case let .recordNumber(attribute):
146146
CornerRadiusText("No Label: \(attribute.noLabel)")
147147

148+
case let .referenceTable(attribute):
149+
CornerRadiusText("No Label: \(attribute.noLabel)")
150+
CornerRadiusText("Related App/App: \(attribute.referenceTable.relatedApp.appID)")
151+
CornerRadiusText("Related App/Code: \(attribute.referenceTable.relatedApp.code)")
152+
CornerRadiusText("Condition/Field: \(attribute.referenceTable.condition.field)")
153+
CornerRadiusText("Condition/Related Field: \(attribute.referenceTable.condition.relatedField)")
154+
CornerRadiusText("Filter Condition: \(attribute.referenceTable.filterCondition)")
155+
CornerRadiusText("Display Fields: \(attribute.referenceTable.displayFields.joined(separator: ","))")
156+
CornerRadiusText("Sort: \(attribute.referenceTable.sort)")
157+
CornerRadiusText("Size: \(attribute.referenceTable.size)")
158+
148159
case let .richText(attribute):
149160
CornerRadiusText("No Label: \(attribute.noLabel)")
150161
CornerRadiusText("Required: \(attribute.required)")
@@ -153,8 +164,8 @@ struct FieldDetailView: View {
153164
case let .singleLineText(attribute):
154165
CornerRadiusText("No Label: \(attribute.noLabel)")
155166
CornerRadiusText("Required: \(attribute.required)")
156-
CornerRadiusText("Min Length: \(attribute.minLength)")
157-
CornerRadiusText("Max Length: \(attribute.maxLength)")
167+
CornerRadiusText("Min Length: \(String(optional: attribute.minLength))")
168+
CornerRadiusText("Max Length: \(String(optional: attribute.maxLength))")
158169
CornerRadiusText("Expression: \(attribute.expression)")
159170
CornerRadiusText("Hide Expression: \(attribute.hideExpression)")
160171
CornerRadiusText("Unique: \(attribute.unique)")

Sources/KintoneAPI/Decodable/FetchFieldsResponse.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
struct FetchFieldsResponse: Decodable {
99
var properties: [FieldProperty]
10+
var revision: Int
1011

11-
enum CodingKeys: String, CodingKey {
12+
enum CodingKeys: CodingKey {
1213
case properties
14+
case revision
1315
}
1416

1517
init(from decoder: any Decoder) throws {
@@ -18,5 +20,6 @@ struct FetchFieldsResponse: Decodable {
1820
properties = try propertiesContainer.allKeys.map { key in
1921
try propertiesContainer.decode(FieldProperty.self, forKey: DynamicCodingKey(stringValue: key.stringValue)!)
2022
}
23+
revision = try container.customDecode(String.self, forKey: .revision) { Int($0) }
2124
}
2225
}

Sources/KintoneAPI/Decodable/Field/FieldAttribute.swift

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public enum FieldAttribute: Sendable {
2626
case organizationSelect(OrganizationSelectAttribute)
2727
case radioButton(RadioButtonAttribute)
2828
case recordNumber(RecordNumberAttribute)
29+
case referenceTable(ReferenceTableAttribute)
2930
case richText(RichTextAttribute)
3031
case singleLineText(SingleLineTextAttribute)
3132
case status(StatusAttribute)

Sources/KintoneAPI/Decodable/Field/FieldAttribute/CalcAttribute.swift

+24-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,30 @@ public struct CalcAttribute: Decodable, Sendable {
1111
public var expression: String
1212
public var hideExpression: Bool
1313
public var format: CalcFormat
14-
public var displayScale: String
14+
public var displayScale: Int?
1515
public var unit: String
1616
public var unitPosition: UnitPosition
17+
18+
enum CodingKeys: CodingKey {
19+
case noLabel
20+
case required
21+
case expression
22+
case hideExpression
23+
case format
24+
case displayScale
25+
case unit
26+
case unitPosition
27+
}
28+
29+
public init(from decoder: any Decoder) throws {
30+
let container = try decoder.container(keyedBy: CodingKeys.self)
31+
noLabel = try container.decode(Bool.self, forKey: .noLabel)
32+
required = try container.decode(Bool.self, forKey: .required)
33+
expression = try container.decode(String.self, forKey: .expression)
34+
hideExpression = try container.decode(Bool.self, forKey: .hideExpression)
35+
format = try container.decode(CalcFormat.self, forKey: .format)
36+
displayScale = Int(try container.decode(String.self, forKey: .displayScale))
37+
unit = try container.decode(String.self, forKey: .unit)
38+
unitPosition = try container.decode(UnitPosition.self, forKey: .unitPosition)
39+
}
1740
}

Sources/KintoneAPI/Decodable/Field/FieldAttribute/FileAttribute.swift

+14-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,18 @@
88
public struct FileAttribute: Decodable, Sendable {
99
public var noLabel: Bool
1010
public var required: Bool
11-
public var thumbnailSize: String
11+
public var thumbnailSize: Int
12+
13+
enum CodingKeys: CodingKey {
14+
case noLabel
15+
case required
16+
case thumbnailSize
17+
}
18+
19+
public init(from decoder: any Decoder) throws {
20+
let container = try decoder.container(keyedBy: CodingKeys.self)
21+
noLabel = try container.decode(Bool.self, forKey: .noLabel)
22+
required = try container.decode(Bool.self, forKey: .required)
23+
thumbnailSize = try container.customDecode(String.self, forKey: .thumbnailSize) { Int($0) }
24+
}
1225
}

Sources/KintoneAPI/Decodable/Field/FieldAttribute/LinkAttribute.swift

+13-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public struct LinkAttribute: Decodable, Sendable {
99
public var noLabel: Bool
1010
public var required: Bool
1111
public var linkProtocol: LinkProtocol
12-
public var minLength: String
13-
public var maxLength: String
12+
public var minLength: Int?
13+
public var maxLength: Int?
1414
public var unique: Bool
1515
public var defaultValue: String
1616

@@ -23,4 +23,15 @@ public struct LinkAttribute: Decodable, Sendable {
2323
case unique
2424
case defaultValue
2525
}
26+
27+
public init(from decoder: any Decoder) throws {
28+
let container = try decoder.container(keyedBy: CodingKeys.self)
29+
noLabel = try container.decode(Bool.self, forKey: .noLabel)
30+
required = try container.decode(Bool.self, forKey: .required)
31+
linkProtocol = try container.decode(LinkProtocol.self, forKey: .linkProtocol)
32+
minLength = Int(try container.decode(String.self, forKey: .minLength))
33+
maxLength = Int(try container.decode(String.self, forKey: .maxLength))
34+
unique = try container.decode(Bool.self, forKey: .unique)
35+
defaultValue = try container.decode(String.self, forKey: .defaultValue)
36+
}
2637
}

Sources/KintoneAPI/Decodable/Field/FieldAttribute/NumberAttribute.swift

+31-4
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,39 @@
88
public struct NumberAttribute: Decodable, Sendable {
99
public var noLabel: Bool
1010
public var required: Bool
11-
public var minValue: String
12-
public var maxValue: String
11+
public var minValue: Int?
12+
public var maxValue: Int?
1313
public var digit: Bool
1414
public var unique: Bool
1515
public var defaultValue: String
16-
public var displayScale: String
16+
public var displayScale: Int?
1717
public var unit: String
18-
public var unitPosition: String
18+
public var unitPosition: UnitPosition
19+
20+
enum CodingKeys: CodingKey {
21+
case noLabel
22+
case required
23+
case minValue
24+
case maxValue
25+
case digit
26+
case unique
27+
case defaultValue
28+
case displayScale
29+
case unit
30+
case unitPosition
31+
}
32+
33+
public init(from decoder: any Decoder) throws {
34+
let container = try decoder.container(keyedBy: CodingKeys.self)
35+
noLabel = try container.decode(Bool.self, forKey: .noLabel)
36+
required = try container.decode(Bool.self, forKey: .required)
37+
minValue = Int(try container.decode(String.self, forKey: .minValue))
38+
maxValue = Int(try container.decode(String.self, forKey: .maxValue))
39+
digit = try container.decode(Bool.self, forKey: .digit)
40+
unique = try container.decode(Bool.self, forKey: .unique)
41+
defaultValue = try container.decode(String.self, forKey: .defaultValue)
42+
displayScale = Int(try container.decode(String.self, forKey: .displayScale))
43+
unit = try container.decode(String.self, forKey: .unit)
44+
unitPosition = try container.decode(UnitPosition.self, forKey: .unitPosition)
45+
}
1946
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// ReferenceTableAttribute.swift
3+
//
4+
//
5+
// Created by ky0me22 on 2025/02/11.
6+
//
7+
8+
public struct ReferenceTableAttribute: Decodable, Sendable {
9+
public var noLabel: Bool
10+
public var referenceTable: ReferenceTable
11+
}

Sources/KintoneAPI/Decodable/Field/FieldAttribute/SingleLineTextAttribute.swift

+25-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,33 @@
88
public struct SingleLineTextAttribute: Decodable, Sendable {
99
public var noLabel: Bool
1010
public var required: Bool
11-
public var minLength: String
12-
public var maxLength: String
11+
public var minLength: Int?
12+
public var maxLength: Int?
1313
public var expression: String
1414
public var hideExpression: Bool
1515
public var unique: Bool
1616
public var defaultValue: String
17+
18+
enum CodingKeys: CodingKey {
19+
case noLabel
20+
case required
21+
case minLength
22+
case maxLength
23+
case expression
24+
case hideExpression
25+
case unique
26+
case defaultValue
27+
}
28+
29+
public init(from decoder: any Decoder) throws {
30+
let container = try decoder.container(keyedBy: CodingKeys.self)
31+
noLabel = try container.decode(Bool.self, forKey: .noLabel)
32+
required = try container.decode(Bool.self, forKey: .required)
33+
minLength = Int(try container.decode(String.self, forKey: .minLength))
34+
maxLength = Int(try container.decode(String.self, forKey: .maxLength))
35+
expression = try container.decode(String.self, forKey: .expression)
36+
hideExpression = try container.decode(Bool.self, forKey: .hideExpression)
37+
unique = try container.decode(Bool.self, forKey: .unique)
38+
defaultValue = try container.decode(String.self, forKey: .defaultValue)
39+
}
1740
}

Sources/KintoneAPI/Decodable/Field/FieldOption.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@
77

88
public struct FieldOption: Decodable, Sendable {
99
public var label: String
10-
public var index: String
10+
public var index: Int
11+
12+
enum CodingKeys: CodingKey {
13+
case label
14+
case index
15+
}
16+
17+
public init(from decoder: any Decoder) throws {
18+
let container = try decoder.container(keyedBy: CodingKeys.self)
19+
label = try container.decode(String.self, forKey: .label)
20+
index = try container.customDecode(String.self, forKey: .index) { Int($0) }
21+
}
1122
}
1223

1324
struct FieldOptions: Decodable, Sendable {

Sources/KintoneAPI/Decodable/Field/FieldProperty.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public struct FieldProperty: Decodable, Sendable {
1111
public var type: FieldType
1212
public var attribute: FieldAttribute
1313

14-
enum CodingKeys: String, CodingKey {
14+
enum CodingKeys: CodingKey {
1515
case code
1616
case label
1717
case type
@@ -65,6 +65,8 @@ public struct FieldProperty: Decodable, Sendable {
6565
try FieldAttribute.radioButton(RadioButtonAttribute(from: decoder))
6666
case .recordNumber:
6767
try FieldAttribute.recordNumber(RecordNumberAttribute(from: decoder))
68+
case .referenceTable:
69+
try FieldAttribute.referenceTable(ReferenceTableAttribute(from: decoder))
6870
case .richText:
6971
try FieldAttribute.richText(RichTextAttribute(from: decoder))
7072
case .singleLineText:

Sources/KintoneAPI/Decodable/Field/FieldType.swift

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public enum FieldType: String, Decodable, Sendable {
2525
case organizationSelect = "ORGANIZATION_SELECT"
2626
case radioButton = "RADIO_BUTTON"
2727
case recordNumber = "RECORD_NUMBER"
28+
case referenceTable = "REFERENCE_TABLE"
2829
case richText = "RICH_TEXT"
2930
case singleLineText = "SINGLE_LINE_TEXT"
3031
case status = "STATUS"

Sources/KintoneAPI/Decodable/Field/ReferenceTable.swift

+11-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public struct ReferenceTable: Decodable, Sendable {
1111
public var filterCondition: String
1212
public var displayFields: [String]
1313
public var sort: String
14-
public var size: String
14+
public var size: Int
1515

1616
enum CodingKeys: String, CodingKey {
1717
case relatedApp
@@ -21,4 +21,14 @@ public struct ReferenceTable: Decodable, Sendable {
2121
case sort
2222
case size
2323
}
24+
25+
public init(from decoder: any Decoder) throws {
26+
let container = try decoder.container(keyedBy: CodingKeys.self)
27+
relatedApp = try container.decode(RelatedApp.self, forKey: .relatedApp)
28+
condition = try container.decode(ReferenceCondition.self, forKey: .condition)
29+
filterCondition = try container.decode(String.self, forKey: .filterCondition)
30+
displayFields = try container.decode([String].self, forKey: .displayFields)
31+
sort = try container.decode(String.self, forKey: .sort)
32+
size = try container.customDecode(String.self, forKey: .size) { Int($0) }
33+
}
2434
}

Sources/KintoneAPI/Decodable/Field/RelatedApp.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
//
77

88
public struct RelatedApp: Decodable, Sendable {
9-
public var app: String
9+
public var appID: Int
1010
public var code: String
11+
12+
enum CodingKeys: String, CodingKey {
13+
case appID = "app"
14+
case code
15+
}
16+
17+
public init(from decoder: any Decoder) throws {
18+
let container = try decoder.container(keyedBy: CodingKeys.self)
19+
appID = try container.customDecode(String.self, forKey: .appID) { Int($0) }
20+
code = try container.decode(String.self, forKey: .code)
21+
}
1122
}

Sources/KintoneAPI/Decodable/Record/Record+Read.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ extension Record {
1515
let id = try container.customDecode(RecordFieldValue.Read.self, forKey: DynamicCodingKey(stringValue: "$id")!) { $0.integer }
1616
let revision = try container.customDecode(RecordFieldValue.Read.self, forKey: DynamicCodingKey(stringValue: "$revision")!) { $0.integer }
1717
identity = RecordIdentity.Read(id: id, revision: revision)
18-
fields = try container.allKeys.map { key in
18+
let keys = container.allKeys.filter { !["$id", "$revision"].contains($0.stringValue) }
19+
fields = try keys.map { key in
1920
let value = try container.decode(RecordFieldValue.Read.self, forKey: DynamicCodingKey(stringValue: key.stringValue)!)
2021
return RecordField.Read(code: key.stringValue, value: value)
2122
}

Sources/KintoneAPI/Decodable/Record/RecordFieldValue+Read.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ extension RecordFieldValue {
7575
let entities = try container.customDecode([EntityValue].self, forKey: .value) {
7676
$0.map { Entity.Read(type: .group, code: $0.code, name: $0.name) }
7777
}
78-
self = .userSelect(entities)
78+
self = .groupSelect(entities)
7979
case .id:
8080
self = .id(try container.customDecode(String.self, forKey: .value, initializer: { Int($0) }))
8181
case .link:

0 commit comments

Comments
 (0)