@knpkv/clockify-api-client 1.0.0 → 1.0.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.
@@ -80,6 +80,72 @@ describe("ClockifyApiClient", () => {
80
80
  )
81
81
  })
82
82
 
83
+ it.effect("decodes a created time entry whose optional id references are null", () => {
84
+ const requests: Array<HttpClientRequest.HttpClientRequest> = []
85
+ return Effect.gen(function*() {
86
+ const client = yield* ClockifyApiClient
87
+ // Clockify returns kioskId/projectId/taskId as explicit null (not absent) when unset.
88
+ const entry = yield* client.createTimeEntry("workspace-1", {
89
+ description: "[RPS-6169] review transaction mapper",
90
+ start: "2026-07-20T09:00:00Z"
91
+ })
92
+ expect(entry.id).toBe("entry-1")
93
+ expect(entry.kioskId).toBeNull()
94
+ expect(entry.projectId).toBeNull()
95
+ expect(entry.taskId).toBeNull()
96
+ expect(entry.tagIds).toBeNull()
97
+ }).pipe(
98
+ Effect.provide(clientLayer({
99
+ status: 201,
100
+ body: {
101
+ id: "entry-1",
102
+ description: "[RPS-6169] review transaction mapper",
103
+ billable: true,
104
+ userId: "user-1",
105
+ workspaceId: "workspace-1",
106
+ kioskId: null,
107
+ projectId: null,
108
+ taskId: null,
109
+ tagIds: null,
110
+ timeInterval: {
111
+ start: "2026-07-20T09:00:00Z",
112
+ end: null,
113
+ duration: null
114
+ }
115
+ }
116
+ }, requests))
117
+ )
118
+ })
119
+
120
+ it.effect("decodes a time-entries list whose entries have null tagIds", () => {
121
+ const requests: Array<HttpClientRequest.HttpClientRequest> = []
122
+ return Effect.gen(function*() {
123
+ const client = yield* ClockifyApiClient
124
+ // `jcf sync reconcile` fetches time entries; Clockify returns tagIds as
125
+ // null (not an empty array) for entries with no tags.
126
+ const entries = yield* client.getTimeEntries("workspace-1", "user-1")
127
+ expect(entries).toHaveLength(1)
128
+ expect(entries[0]?.tagIds).toBeNull()
129
+ }).pipe(
130
+ Effect.provide(clientLayer({
131
+ status: 200,
132
+ body: [{
133
+ id: "entry-1",
134
+ description: "[RPS-6169] review transaction mapper",
135
+ billable: true,
136
+ userId: "user-1",
137
+ workspaceId: "workspace-1",
138
+ tagIds: null,
139
+ timeInterval: {
140
+ start: "2026-07-20T09:00:00Z",
141
+ end: "2026-07-20T11:00:00Z",
142
+ duration: "PT2H"
143
+ }
144
+ }]
145
+ }, requests))
146
+ )
147
+ })
148
+
83
149
  it.effect("leaves multipart content type unset so the transport can add its boundary", () => {
84
150
  const requests: Array<HttpClientRequest.HttpClientRequest> = []
85
151
  const httpClient = HttpClient.make((request) =>