eintopf.info@v0.13.16/service/revent/revent_test.go (about)

     1  // Copyright (C) 2022 The Eintopf authors
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  
    16  package revent_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"github.com/google/go-cmp/cmp/cmpopts"
    26  
    27  	"eintopf.info/service/auth"
    28  	"eintopf.info/service/event"
    29  	"eintopf.info/service/revent"
    30  	"eintopf.info/test"
    31  )
    32  
    33  func tptr(t time.Time) *time.Time {
    34  	return &t
    35  }
    36  
    37  func TestIntervalGenerateDates(t *testing.T) {
    38  	tests := []struct {
    39  		name      string
    40  		interval  *revent.Interval
    41  		start     time.Time
    42  		end       time.Time
    43  		wantDates []time.Time
    44  	}{
    45  		{
    46  			name: "daily",
    47  			interval: &revent.Interval{
    48  				Type:     revent.IntervalDay,
    49  				Interval: 1,
    50  			},
    51  			start: time.Date(2021, 8, 10, 16, 0, 0, 0, time.UTC),
    52  			end:   time.Date(2021, 8, 15, 16, 0, 0, 0, time.UTC),
    53  			wantDates: []time.Time{
    54  				time.Date(2021, 8, 10, 16, 0, 0, 0, time.UTC),
    55  				time.Date(2021, 8, 11, 16, 0, 0, 0, time.UTC),
    56  				time.Date(2021, 8, 12, 16, 0, 0, 0, time.UTC),
    57  				time.Date(2021, 8, 13, 16, 0, 0, 0, time.UTC),
    58  				time.Date(2021, 8, 14, 16, 0, 0, 0, time.UTC),
    59  				time.Date(2021, 8, 15, 16, 0, 0, 0, time.UTC),
    60  			},
    61  		},
    62  		{
    63  			name: "every second day",
    64  			interval: &revent.Interval{
    65  				Type:     revent.IntervalDay,
    66  				Interval: 2,
    67  			},
    68  			start: time.Date(2021, 8, 10, 16, 0, 0, 0, time.UTC),
    69  			end:   time.Date(2021, 8, 15, 16, 0, 0, 0, time.UTC),
    70  			wantDates: []time.Time{
    71  				time.Date(2021, 8, 10, 16, 0, 0, 0, time.UTC),
    72  				time.Date(2021, 8, 12, 16, 0, 0, 0, time.UTC),
    73  				time.Date(2021, 8, 14, 16, 0, 0, 0, time.UTC),
    74  			},
    75  		},
    76  		{
    77  			name: "every monday",
    78  			interval: &revent.Interval{
    79  				Type:     revent.IntervalWeek,
    80  				Interval: 1,
    81  				WeekDay:  time.Monday,
    82  			},
    83  			start: time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
    84  			end:   time.Date(2021, 9, 1, 16, 0, 0, 0, time.UTC),
    85  			wantDates: []time.Time{
    86  				time.Date(2021, 8, 2, 16, 0, 0, 0, time.UTC),
    87  				time.Date(2021, 8, 9, 16, 0, 0, 0, time.UTC),
    88  				time.Date(2021, 8, 16, 16, 0, 0, 0, time.UTC),
    89  				time.Date(2021, 8, 23, 16, 0, 0, 0, time.UTC),
    90  				time.Date(2021, 8, 30, 16, 0, 0, 0, time.UTC),
    91  			},
    92  		},
    93  		{
    94  			name: "every second thursday",
    95  			interval: &revent.Interval{
    96  				Type:     revent.IntervalWeek,
    97  				Interval: 2,
    98  				WeekDay:  time.Thursday,
    99  			},
   100  			start: time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   101  			end:   time.Date(2021, 9, 1, 16, 0, 0, 0, time.UTC),
   102  			wantDates: []time.Time{
   103  				time.Date(2021, 8, 5, 16, 0, 0, 0, time.UTC),
   104  				time.Date(2021, 8, 19, 16, 0, 0, 0, time.UTC),
   105  			},
   106  		},
   107  		{
   108  			name: "every first friday per month",
   109  			interval: &revent.Interval{
   110  				Type:     revent.IntervalMonth,
   111  				Interval: 1,
   112  				WeekDay:  time.Friday,
   113  			},
   114  			start: time.Date(2021, 8, 1, 18, 30, 0, 0, time.UTC),
   115  			end:   time.Date(2021, 11, 1, 18, 30, 0, 0, time.UTC),
   116  			wantDates: []time.Time{
   117  				time.Date(2021, 8, 6, 18, 30, 0, 0, time.UTC),
   118  				time.Date(2021, 9, 3, 18, 30, 0, 0, time.UTC),
   119  				time.Date(2021, 10, 1, 18, 30, 0, 0, time.UTC),
   120  			},
   121  		},
   122  		{
   123  			name: "every second sunday per month",
   124  			interval: &revent.Interval{
   125  				Type:     revent.IntervalMonth,
   126  				Interval: 2,
   127  				WeekDay:  time.Sunday,
   128  			},
   129  			start: time.Date(2021, 8, 1, 18, 30, 0, 0, time.UTC),
   130  			end:   time.Date(2021, 11, 1, 18, 30, 0, 0, time.UTC),
   131  			wantDates: []time.Time{
   132  				time.Date(2021, 8, 8, 18, 30, 0, 0, time.UTC),
   133  				time.Date(2021, 9, 12, 18, 30, 0, 0, time.UTC),
   134  				time.Date(2021, 10, 10, 18, 30, 0, 0, time.UTC),
   135  			},
   136  		},
   137  	}
   138  
   139  	for _, test := range tests {
   140  		t.Run(test.name, func(tt *testing.T) {
   141  			dates, err := test.interval.GenerateDates(test.start, test.end)
   142  			if err != nil {
   143  				tt.Error(err)
   144  			}
   145  			if diff := cmp.Diff(test.wantDates, dates); diff != "" {
   146  				tt.Errorf("dates mismatch (-want +got):\n%s", diff)
   147  			}
   148  		})
   149  	}
   150  }
   151  
   152  func TestServiceGenerateEvents(t *testing.T) {
   153  	tests := []struct {
   154  		name              string
   155  		newRepeatingEvent *revent.NewRepeatingEvent
   156  		wantErr           error
   157  		wantFirstEvent    *event.Event
   158  		wantEventsCount   int
   159  	}{
   160  		{
   161  			name: "it works",
   162  			newRepeatingEvent: &revent.NewRepeatingEvent{
   163  				Name:        "foo",
   164  				Organizers:  []string{"a", "b"},
   165  				Location:    "c",
   166  				Location2:   "d",
   167  				Description: "e",
   168  				Intervals: []revent.Interval{
   169  					{
   170  						Type:     revent.IntervalDay,
   171  						Interval: 1,
   172  					},
   173  				},
   174  				Start:   time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   175  				End:     time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC),
   176  				Tags:    []string{"x", "y", "z"},
   177  				Image:   "i",
   178  				OwnedBy: []string{"user1", "user2"},
   179  			},
   180  			wantEventsCount: 31,
   181  			wantFirstEvent: &event.Event{
   182  				Published:   true,
   183  				Name:        "foo",
   184  				Organizers:  []string{"a", "b"},
   185  				Location:    "c",
   186  				Location2:   "d",
   187  				Description: "e",
   188  				Start:       time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   189  				End:         tptr(time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC)),
   190  				Tags:        []string{"x", "y", "z"},
   191  				Image:       "i",
   192  				OwnedBy:     []string{"user1", "user2", "1"},
   193  			},
   194  		},
   195  	}
   196  
   197  	for _, testCase := range tests {
   198  		t.Run(testCase.name, func(tt *testing.T) {
   199  			reventStore := revent.NewMemoryStore()
   200  			eventStore := event.NewMemoryStore()
   201  
   202  			service := revent.NewService(reventStore, event.NewService(eventStore, nil))
   203  
   204  			ctx := auth.ContextWithID(context.Background(), "1")
   205  
   206  			repeatingEvent, err := service.Create(ctx, testCase.newRepeatingEvent)
   207  			if err != nil {
   208  				tt.Fatal(err)
   209  			}
   210  
   211  			events, err := service.GenerateEvents(ctx, repeatingEvent.ID,
   212  				time.Date(2021, 8, 1, 0, 0, 0, 0, time.UTC),
   213  				time.Date(2021, 8, 31, 0, 0, 0, 0, time.UTC),
   214  			)
   215  			if !test.EqualError(testCase.wantErr, err) {
   216  				tt.Errorf("err: want != got: %s, %s", testCase.wantErr, err)
   217  			}
   218  			if len(events) != testCase.wantEventsCount {
   219  				tt.Errorf("events len: want != got: %d, %d", testCase.wantEventsCount, len(events))
   220  			}
   221  			if len(events) > 0 && testCase.wantFirstEvent != nil {
   222  				testCase.wantFirstEvent.Parent = revent.ID(repeatingEvent.ID)
   223  				if diff := cmp.Diff(testCase.wantFirstEvent, events[0], cmpopts.IgnoreFields(event.Event{}, "ID")); diff != "" {
   224  					tt.Errorf("first event mismatch mismatch (-want +got):\n%s", diff)
   225  				}
   226  			}
   227  		})
   228  	}
   229  }
   230  
   231  func TestGenerateEvents(t *testing.T) {
   232  	tests := []struct {
   233  		name               string
   234  		repeatingEvent     *revent.RepeatingEvent
   235  		existingEvents     []*event.Event
   236  		wantErr            error
   237  		wantFirstNewEvent  *event.NewEvent
   238  		wantNewEventsCount int
   239  	}{
   240  		{
   241  			name: "no intervals error",
   242  			repeatingEvent: &revent.RepeatingEvent{
   243  				ID:          "1",
   244  				Name:        "foo",
   245  				Organizers:  []string{"a"},
   246  				Location:    "c",
   247  				Location2:   "d",
   248  				Description: "e",
   249  				Intervals:   []revent.Interval{},
   250  				Start:       time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   251  				End:         time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC),
   252  				Tags:        []string{"x", "y", "z"},
   253  				Image:       "i",
   254  				OwnedBy:     []string{"user1", "user2"},
   255  			},
   256  			wantErr: fmt.Errorf("repeating event has no intervals"),
   257  		},
   258  		{
   259  			name: "generate with IntervalDay",
   260  			repeatingEvent: &revent.RepeatingEvent{
   261  				ID:          "2",
   262  				Name:        "foo",
   263  				Organizers:  []string{"a"},
   264  				Location:    "c",
   265  				Location2:   "d",
   266  				Description: "e",
   267  				Intervals: []revent.Interval{
   268  					{
   269  						Type:     revent.IntervalDay,
   270  						Interval: 1,
   271  					},
   272  				},
   273  				Start:   time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   274  				End:     time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC),
   275  				Tags:    []string{"x", "y", "z"},
   276  				Image:   "i",
   277  				OwnedBy: []string{"user1", "user2"},
   278  			},
   279  			wantNewEventsCount: 31,
   280  			wantFirstNewEvent: &event.NewEvent{
   281  				Published:   true,
   282  				Name:        "foo",
   283  				Organizers:  []string{"a"},
   284  				Location:    "c",
   285  				Location2:   "d",
   286  				Description: "e",
   287  				Start:       time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   288  				End:         tptr(time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC)),
   289  				Tags:        []string{"x", "y", "z"},
   290  				Image:       "i",
   291  				OwnedBy:     []string{"user1", "user2"},
   292  			},
   293  		},
   294  		{
   295  			name: "has existingEvents",
   296  			repeatingEvent: &revent.RepeatingEvent{
   297  				ID:          "2",
   298  				Name:        "foo",
   299  				Organizers:  []string{"a", "b"},
   300  				Location:    "c",
   301  				Location2:   "d",
   302  				Description: "e",
   303  				Intervals: []revent.Interval{
   304  					{
   305  						Type:     revent.IntervalDay,
   306  						Interval: 1,
   307  					},
   308  				},
   309  				Start:   time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   310  				End:     time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC),
   311  				Tags:    []string{"x", "y", "z"},
   312  				Image:   "i",
   313  				OwnedBy: []string{"user1", "user2"},
   314  			},
   315  			existingEvents: []*event.Event{
   316  				{
   317  					Published:   true,
   318  					Name:        "foo",
   319  					Organizers:  []string{"a", "b"},
   320  					Location:    "c",
   321  					Location2:   "d",
   322  					Description: "e",
   323  					Start:       time.Date(2021, 8, 1, 16, 0, 0, 0, time.UTC),
   324  					End:         tptr(time.Date(2021, 8, 1, 18, 0, 0, 0, time.UTC)),
   325  					Tags:        []string{"x", "y", "z"},
   326  					Image:       "i",
   327  					OwnedBy:     []string{"user1", "user2"},
   328  				},
   329  			},
   330  			wantNewEventsCount: 30,
   331  			wantFirstNewEvent: &event.NewEvent{
   332  				Published:   true,
   333  				Name:        "foo",
   334  				Organizers:  []string{"a", "b"},
   335  				Location:    "c",
   336  				Location2:   "d",
   337  				Description: "e",
   338  				Start:       time.Date(2021, 8, 2, 16, 0, 0, 0, time.UTC),
   339  				End:         tptr(time.Date(2021, 8, 2, 18, 0, 0, 0, time.UTC)),
   340  				Tags:        []string{"x", "y", "z"},
   341  				Image:       "i",
   342  				OwnedBy:     []string{"user1", "user2"},
   343  			},
   344  		},
   345  	}
   346  
   347  	for _, testCase := range tests {
   348  		t.Run(testCase.name, func(tt *testing.T) {
   349  			events, err := revent.GenerateEvents(
   350  				testCase.repeatingEvent,
   351  				testCase.existingEvents,
   352  				time.Date(2021, 8, 1, 0, 0, 0, 0, time.UTC),
   353  				time.Date(2021, 8, 31, 0, 0, 0, 0, time.UTC),
   354  			)
   355  			if !test.EqualError(testCase.wantErr, err) {
   356  				tt.Errorf("err: want != got: %s, %s", testCase.wantErr, err)
   357  			}
   358  			if len(events) != testCase.wantNewEventsCount {
   359  				tt.Errorf("new events len: want != got: %d, %d", testCase.wantNewEventsCount, len(events))
   360  			}
   361  			if len(events) > 0 && testCase.wantFirstNewEvent != nil {
   362  				testCase.wantFirstNewEvent.Parent = revent.ID(testCase.repeatingEvent.ID)
   363  				if diff := cmp.Diff(testCase.wantFirstNewEvent, events[0], cmpopts.IgnoreFields(event.Event{}, "ID")); diff != "" {
   364  					tt.Errorf("first event mismatch mismatch (-want +got):\n%s", diff)
   365  				}
   366  			}
   367  		})
   368  	}
   369  }