Completed
Push — master ( 7ca05e...d13f3d )
by Stanislav
01:39
created

client.TestTogglClient_GetPendingEntries   B

Complexity

Conditions 1

Size

Total Lines 61
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 41
nop 1
dl 0
loc 61
rs 8.896
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
package client
2
3
import (
4
	"testing"
5
	"log"
6
	"github.com/viasite/planfix-toggl-server/app/config"
7
	"github.com/popstas/planfix-go/planfix"
8
	"net/http/httptest"
9
	"net/http"
10
	"io/ioutil"
11
	"encoding/xml"
12
	"github.com/popstas/go-toggl"
13
	"reflect"
14
	"time"
15
	"bytes"
16
	"strings"
17
	"github.com/stretchr/testify/assert"
18
	"github.com/stretchr/testify/mock"
19
)
20
21
var output bytes.Buffer
22
23
type planfixRequestStruct struct {
24
	XMLName xml.Name `xml:"request"`
25
	Method  string   `xml:"method,attr"`
26
	Account string   `xml:"account"`
27
	Sid     string   `xml:"sid"`
28
}
29
30
func fixtureFromFile(fixtureName string) string {
31
	buf, _ := ioutil.ReadFile("../../tests/fixtures/" + fixtureName)
32
	return string(buf)
33
}
34
35
type MockedServer struct {
36
	*httptest.Server
37
	Requests  [][]byte
38
	Responses []string // fifo queue of answers
39
}
40
41
func NewMockedServer(responses []string) *MockedServer {
42
	s := &MockedServer{
43
		Requests:  [][]byte{},
44
		Responses: responses,
45
	}
46
47
	s.Server = httptest.NewServer(s)
48
	return s
49
}
50
51
func (s *MockedServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
52
	lastRequest, err := ioutil.ReadAll(req.Body)
53
	if err != nil {
54
		panic(err)
55
	}
56
57
	rs := planfixRequestStruct{}
58
	err = xml.Unmarshal(lastRequest, &rs)
59
	if err != nil {
60
		panic(err)
61
	}
62
	s.Requests = append(s.Requests, lastRequest)
63
	answer := s.Responses[0]
64
65
	s.Responses = s.Responses[1:]
66
	resp.Write([]byte(answer))
67
}
68
69
type MockedTogglSession struct {
70
	mock.Mock
71
	TogglSession
72
}
73
74
func (s *MockedTogglSession) GetAccount() (toggl.Account, error) {
75
	args := s.Called()
76
	return args.Get(0).(toggl.Account), args.Error(1)
77
}
78
79
func (s *MockedTogglSession) GetDetailedReport(workspace int, since, until string, page int) (toggl.DetailedReport, error) {
80
	args := s.Called(workspace, since, until, page)
81
	return args.Get(0).(toggl.DetailedReport), args.Error(1)
82
}
83
84
func (s *MockedTogglSession) AddRemoveTag(entryID int, tag string, add bool) (toggl.TimeEntry, error) {
85
	args := s.Called(entryID, tag, add)
86
	return args.Get(0).(toggl.TimeEntry), args.Error(1)
87
}
88
89
func newClient() TogglClient {
90
	cfg := config.Config{
91
		TogglSentTag: "sent",
92
	}
93
	api := planfix.New("", "apiKey", "account", "user", "password")
94
	api.Sid = "123"
95
96
	sess := &MockedTogglSession{}
97
	return TogglClient{
98
		Session:    sess,
99
		Config:     &cfg,
100
		PlanfixAPI: api,
101
		Logger:     log.New(&output, "", log.LstdFlags),
102
	}
103
}
104
105
func getTestEntries() []TogglPlanfixEntry {
106
	return []TogglPlanfixEntry{
107
		{
108
			toggl.DetailedTimeEntry{Duration: 1},
109
			PlanfixEntryData{TaskID: 1, GroupCount: 1},
110
		},
111
		{
112
			toggl.DetailedTimeEntry{Duration: 2},
113
			PlanfixEntryData{TaskID: 1, GroupCount: 1},
114
		},
115
		{
116
			toggl.DetailedTimeEntry{Duration: 3},
117
			PlanfixEntryData{TaskID: 2, GroupCount: 1},
118
		},
119
		{
120
			toggl.DetailedTimeEntry{Duration: 4},
121
			PlanfixEntryData{TaskID: 2, GroupCount: 1},
122
		},
123
		{
124
			toggl.DetailedTimeEntry{Duration: 5},
125
			PlanfixEntryData{TaskID: 2, GroupCount: 1},
126
		},
127
		{
128
			toggl.DetailedTimeEntry{Duration: 6},
129
			PlanfixEntryData{TaskID: 3, GroupCount: 1},
130
		},
131
	}
132
}
133
134
func getTestGroupedEntries() map[int][]TogglPlanfixEntry {
135
	return map[int][]TogglPlanfixEntry{
136
		1: {
137
			{
138
				toggl.DetailedTimeEntry{Duration: 1},
139
				PlanfixEntryData{TaskID: 1, GroupCount: 1},
140
			},
141
			{
142
				toggl.DetailedTimeEntry{Duration: 2},
143
				PlanfixEntryData{TaskID: 1, GroupCount: 1},
144
			},
145
		},
146
		2: {
147
			{
148
				toggl.DetailedTimeEntry{Duration: 3},
149
				PlanfixEntryData{TaskID: 2, GroupCount: 1},
150
			},
151
			{
152
				toggl.DetailedTimeEntry{Duration: 4},
153
				PlanfixEntryData{TaskID: 2, GroupCount: 1},
154
			},
155
			{
156
				toggl.DetailedTimeEntry{Duration: 5},
157
				PlanfixEntryData{TaskID: 2, GroupCount: 1},
158
			},
159
		},
160
		3: {
161
			{
162
				toggl.DetailedTimeEntry{Duration: 6},
163
				PlanfixEntryData{TaskID: 3, GroupCount: 1},
164
			},
165
		},
166
	}
167
}
168
169
func TestTogglClient_SumEntriesGroup(t *testing.T) {
170
	c := newClient()
171
	groupedEntries := getTestGroupedEntries()
172
	expected := []TogglPlanfixEntry{
173
		{
174
			toggl.DetailedTimeEntry{Duration: 3},
175
			PlanfixEntryData{TaskID: 1, GroupCount: 2},
176
		},
177
		{
178
			toggl.DetailedTimeEntry{Duration: 12},
179
			PlanfixEntryData{TaskID: 2, GroupCount: 3},
180
		},
181
		{
182
			toggl.DetailedTimeEntry{Duration: 6},
183
			PlanfixEntryData{TaskID: 3, GroupCount: 1},
184
		},
185
	}
186
187
	summed := c.SumEntriesGroup(groupedEntries)
188
	equals := reflect.DeepEqual(summed, expected)
189
	assert.Equal(t, equals, true)
190
}
191
192
func TestTogglClient_GroupEntriesByTask(t *testing.T) {
193
	c := newClient()
194
	entries := getTestEntries()
195
	expected := getTestGroupedEntries()
196
197
	grouped := c.GroupEntriesByTask(entries)
198
	equals := reflect.DeepEqual(grouped, expected)
199
	assert.Equal(t, equals, true)
200
}
201
202
func TestTogglClient_GroupEntriesByTask_empty(t *testing.T) {
203
	c := newClient()
204
	entries := []TogglPlanfixEntry{}
205
	expected := map[int][]TogglPlanfixEntry{}
206
207
	grouped := c.GroupEntriesByTask(entries)
208
	equals := reflect.DeepEqual(grouped, expected)
209
	assert.Equal(t, equals, true)
210
}
211
212
func TestTogglClient_sendEntries_dryRun(t *testing.T) {
213
	c := newClient()
214
	c.Config.DryRun = true
215
	now := time.Now()
216
	entries := []TogglPlanfixEntry{
217
		{
218
			toggl.DetailedTimeEntry{
219
				Duration:    60000,
220
				Start:       &now,
221
				Project:     "project",
222
				Description: "description",
223
			},
224
			PlanfixEntryData{TaskID: 1, GroupCount: 1},
225
		},
226
		{
227
			toggl.DetailedTimeEntry{Duration: 120000},
228
			PlanfixEntryData{TaskID: 1, GroupCount: 1},
229
		},
230
	}
231
232
	c.sendEntries(1, entries)
233
	assert.Equal(t, strings.Contains(output.String(), "[DEBUG] sending [project] description (3)"), true)
234
	assert.Equal(t, strings.Contains(output.String(), "[DEBUG] dry-run"), true)
235
}
236
237
func TestTogglClient_GetTogglUserID(t *testing.T) {
238
	c := newClient()
239
	sess := &MockedTogglSession{}
240
	c.Session = sess
241
242
	togglUser := toggl.Account{Data: struct {
243
		APIToken        string            `json:"api_token"`
244
		Timezone        string            `json:"timezone"`
245
		ID              int               `json:"id"`
246
		Workspaces      []toggl.Workspace `json:"workspaces"`
247
		Clients         []toggl.Client    `json:"clients"`
248
		Projects        []toggl.Project   `json:"projects"`
249
		Tasks           []toggl.Task      `json:"tasks"`
250
		Tags            []toggl.Tag       `json:"tags"`
251
		TimeEntries     []toggl.TimeEntry `json:"time_entries"`
252
		BeginningOfWeek int               `json:"beginning_of_week"`
253
	}{ID: 123}}
254
	sess.On("GetAccount").Return(togglUser, nil)
255
256
	togglUserID := c.GetTogglUserID()
257
	assert.Equal(t, togglUserID, 123)
258
}
259
260
func TestTogglClient_GetPlanfixUserID(t *testing.T) {
261
	c := newClient()
262
	ms := NewMockedServer([]string{
263
		fixtureFromFile("user.get.xml"),
264
		//fixtureFromFile("error.xml"),
265
	})
266
	c.PlanfixAPI.URL = ms.URL
267
268
	planfixUserID := c.GetPlanfixUserID()
269
	assert.Equal(t, planfixUserID, 9230)
270
}
271
272
func TestTogglClient_GetEntries(t *testing.T) {
273
	c := newClient()
274
	sess := &MockedTogglSession{}
275
	c.Session = sess
276
277
	since := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
278
	until := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
279
	report := toggl.DetailedReport{Data: []toggl.DetailedTimeEntry{
280
		{
281
			ID:          1,
282
			Project:     "project1",
283
			Description: "description1",
284
			Tags:        []string{"12345", "sent"},
285
		},
286
	}}
287
288
	sess.On("GetDetailedReport", 234, since, until, 1).Return(report, nil)
289
290
	report, _ = c.Session.GetDetailedReport(234, since, until, 1)
291
	entries, _ := c.GetEntries(234, since, until)
292
293
	expected := []TogglPlanfixEntry{
294
		{
295
			DetailedTimeEntry: report.Data[0],
296
			Planfix:           PlanfixEntryData{GroupCount: 1, Sent: true, TaskID: 12345},
297
		},
298
	}
299
	assert.Equal(t, entries, expected)
300
}
301
302
func TestTogglClient_GetPendingEntries(t *testing.T) {
303
	c := newClient()
304
	sess := &MockedTogglSession{}
305
	c.Session = sess
306
307
	since := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
308
	until := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
309
	report := toggl.DetailedReport{Data: []toggl.DetailedTimeEntry{
310
		// will be filtered by sent tag
311
		{
312
			ID:          1,
313
			Project:     "project1",
314
			Description: "description1",
315
			Tags:        []string{"12345", "sent"},
316
		},
317
		{
318
			ID:          2,
319
			Project:     "project1",
320
			Description: "description1",
321
			Tags:        []string{"12345"},
322
		},
323
		// will be filtered by taskID tag
324
		{
325
			ID:          3,
326
			Project:     "project1",
327
			Description: "description1",
328
			Tags:        []string{},
329
		},
330
		{
331
			ID:          4,
332
			Project:     "project1",
333
			Description: "description1",
334
			Tags:        []string{"12345"},
335
		},
336
	}}
337
338
	sess.On("GetDetailedReport", c.Config.TogglWorkspaceID, since, until, 1).Return(report, nil)
339
340
	entries, _ := c.GetPendingEntries()
341
342
	expected := []TogglPlanfixEntry{
343
		{
344
			DetailedTimeEntry: toggl.DetailedTimeEntry{
345
				ID:          2,
346
				Project:     "project1",
347
				Description: "description1",
348
				Tags:        []string{"12345"},
349
			},
350
			Planfix: PlanfixEntryData{GroupCount: 1, Sent: false, TaskID: 12345},
351
		},
352
		{
353
			DetailedTimeEntry: toggl.DetailedTimeEntry{
354
				ID:          4,
355
				Project:     "project1",
356
				Description: "description1",
357
				Tags:        []string{"12345"},
358
			},
359
			Planfix: PlanfixEntryData{GroupCount: 1, Sent: false, TaskID: 12345},
360
		},
361
	}
362
	assert.Equal(t, entries, expected)
363
}
364
365
func TestTogglClient_markAsSent(t *testing.T) {
366
	c := newClient()
367
	sess := &MockedTogglSession{}
368
	c.Session = sess
369
370
	planfixEntries := []TogglPlanfixEntry{
371
		{
372
			DetailedTimeEntry: toggl.DetailedTimeEntry{
373
				ID:          2,
374
				Project:     "project1",
375
				Description: "description1",
376
				Tags:        []string{"12345"},
377
			},
378
			Planfix: PlanfixEntryData{GroupCount: 1, Sent: false, TaskID: 12345},
379
		},
380
		{
381
			DetailedTimeEntry: toggl.DetailedTimeEntry{
382
				ID:          4,
383
				Project:     "project1",
384
				Description: "description1",
385
				Tags:        []string{"12345"},
386
			},
387
			Planfix: PlanfixEntryData{GroupCount: 1, Sent: false, TaskID: 12345},
388
		},
389
	}
390
	togglEntries := []toggl.TimeEntry{
391
		{
392
			ID:          2,
393
			Description: "description1",
394
			Tags:        []string{"12345"},
395
		},
396
		{
397
			ID:          4,
398
			Description: "description1",
399
			Tags:        []string{"12345"},
400
		},
401
	}
402
	sess.On("AddRemoveTag", 2, c.Config.TogglSentTag, true).Return(togglEntries[0], nil)
403
	sess.On("AddRemoveTag", 4, c.Config.TogglSentTag, true).Return(togglEntries[1], nil)
404
405
	err := c.markAsSent(planfixEntries)
406
	assert.NoError(t, err)
407
}
408
409
func TestTogglClient_getTaskEmail(t *testing.T) {
410
	c := newClient()
411
	c.Config.PlanfixAccount = "mycompany"
412
413
	taskEmail := c.getTaskEmail(123)
414
	assert.Equal(t, taskEmail, "[email protected]")
415
}
416
417
func TestTogglClient_getEmailBody(t *testing.T) {
418
	c := newClient()
419
	c.Config.PlanfixAccount = "mycompany"
420
	c.Config.SMTPEmailFrom = "[email protected]"
421
	c.Config.PlanfixAnaliticTypeValue = "Название аналитики"
422
	c.Config.PlanfixAuthorName = "Имя Фамилия"
423
424
	expectedBody := "Content-Type: text/plain; charset=\"utf-8\"\r\n" +
425
		"From: [email protected]\r\n" +
426
		"To: [email protected]\r\n" +
427
		"Subject: @toggl @nonotify\r\n" +
428
		"\r\n" +
429
		"Вид работы: Название аналитики\r\n" +
430
		"time: 234\r\n" +
431
		"Автор: Имя Фамилия\r\n" +
432
		"Дата: 2018-03-04\r\n"
433
434
	body := c.getEmailBody(123, "2018-03-04", 234)
435
	assert.Equal(t, body, expectedBody)
436
}
437
438
func TestTogglClient_GetAnaliticData(t *testing.T) {
439
	c := newClient()
440
	ms := NewMockedServer([]string{
441
		fixtureFromFile("analitic.getList.xml"),
442
		fixtureFromFile("analitic.getOptions.xml"),
443
		fixtureFromFile("analitic.getHandbook.xml"),
444
	})
445
	c.PlanfixAPI.URL = ms.URL
446
	c.Config.PlanfixUserID = 123
447
	c.Config.PlanfixAnaliticName = "Выработка"
448
	c.Config.PlanfixAnaliticTypeName = "Вид работы"
449
	c.Config.PlanfixAnaliticTypeValue = "Поминутная работа программиста"
450
	c.Config.PlanfixAnaliticCountName = "Кол-во"
451
	c.Config.PlanfixAnaliticCommentName = "Комментарий / ссылка"
452
	c.Config.PlanfixAnaliticDateName = "Дата"
453
	c.Config.PlanfixAnaliticUsersName = "Сотрудник"
454
455
	// нормальное поведение
456
	analiticData, err := c.GetAnaliticData(
457
		c.Config.PlanfixAnaliticName,
458
		c.Config.PlanfixAnaliticTypeName,
459
		c.Config.PlanfixAnaliticTypeValue,
460
		c.Config.PlanfixAnaliticCountName,
461
		c.Config.PlanfixAnaliticCommentName,
462
		c.Config.PlanfixAnaliticDateName,
463
		c.Config.PlanfixAnaliticUsersName,
464
	)
465
	assert.NoError(t, err)
466
	assert.Equal(t, analiticData.TypeValueID, 725)
467
468
	// тест кеша
469
	analiticData, err = c.GetAnaliticData("", "", "", "", "", "", "")
470
	assert.NoError(t, err)
471
	assert.Equal(t, analiticData.TypeValueID, 725)
472
473
	// неправильный вид работы
474
	c.analiticData = PlanfixAnaliticData{} // сброс кеша
475
	ms = NewMockedServer([]string{
476
		fixtureFromFile("analitic.getList.xml"),
477
		fixtureFromFile("analitic.getOptions.xml"),
478
		fixtureFromFile("analitic.getHandbook.xml"),
479
	})
480
	c.PlanfixAPI.URL = ms.URL
481
	c.Config.PlanfixAnaliticTypeValue = "Какой-то неизвестный вид работы"
482
	analiticData, err = c.GetAnaliticData(
483
		c.Config.PlanfixAnaliticName,
484
		c.Config.PlanfixAnaliticTypeName,
485
		c.Config.PlanfixAnaliticTypeValue,
486
		c.Config.PlanfixAnaliticCountName,
487
		c.Config.PlanfixAnaliticCommentName,
488
		c.Config.PlanfixAnaliticDateName,
489
		c.Config.PlanfixAnaliticUsersName,
490
	)
491
	assert.Error(t, err)
492
	assert.Equal(t, analiticData.TypeValueID, 0)
493
	assert.Equal(t, analiticData.CommentID, 749)
494
}
495
496
// TODO: проходит метод полностью, но непонятно что проверяет
497
func TestTogglClient_sendWithPlanfixAPI(t *testing.T) {
498
	c := newClient()
499
	c.Config.PlanfixAnaliticName = "Выработка"
500
	c.Config.PlanfixAnaliticTypeName = "Вид работы"
501
	c.Config.PlanfixAnaliticTypeValue = "Поминутная работа программиста"
502
	c.Config.PlanfixAnaliticCountName = "Кол-во"
503
	c.Config.PlanfixAnaliticCommentName = "Комментарий / ссылка"
504
	c.Config.PlanfixAnaliticDateName = "Дата"
505
	c.Config.PlanfixAnaliticUsersName = "Сотрудник"
506
507
	ms := NewMockedServer([]string{
508
		fixtureFromFile("analitic.getList.xml"),
509
		fixtureFromFile("analitic.getOptions.xml"),
510
		fixtureFromFile("analitic.getHandbook.xml"),
511
		fixtureFromFile("action.add.xml"),
512
	})
513
	c.PlanfixAPI.URL = ms.URL
514
	c.Config.PlanfixUserID = 123
515
	c.Config.PlanfixAnaliticName = "Выработка"
516
517
	err := c.sendWithPlanfixAPI(123, "2018-03-04", 234, "comment")
518
	assert.NoError(t, err)
519
}
520