github.com/Financial-Times/publish-availability-monitor@v1.12.0/messageHandler_test.go (about)

     1  package main
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/Financial-Times/go-logger/v2"
     7  	"github.com/Financial-Times/kafka-client-go/v4"
     8  	"github.com/Financial-Times/publish-availability-monitor/content"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  const syntheticTID = "SYNTHETIC-REQ-MONe4d2885f-1140-400b-9407-921e1c7378cd"
    13  const carouselRepublishTID = "tid_ofcysuifp0_carousel_1488384556"
    14  const carouselUnconventionalRepublishTID = "republish_-10bd337c-66d4-48d9-ab8a-e8441fa2ec98_carousel_1493606135"
    15  const carouselGeneratedTID = "tid_ofcysuifp0_carousel_1488384556_gentx"
    16  const naturalTID = "tid_xltcnbckvq"
    17  
    18  func TestIsIgnorableMessage(t *testing.T) {
    19  	tests := map[string]struct {
    20  		TransactionID  string
    21  		ExpectedResult bool
    22  	}{
    23  		"normal message should not be ignored": {
    24  			TransactionID:  naturalTID,
    25  			ExpectedResult: false,
    26  		},
    27  		"synthetic message should be ignored": {
    28  			TransactionID:  syntheticTID,
    29  			ExpectedResult: true,
    30  		},
    31  		"carousel republish message should be ignored": {
    32  			TransactionID:  carouselRepublishTID,
    33  			ExpectedResult: true,
    34  		},
    35  		"carousel unconventional republish message should be ignored": {
    36  			TransactionID:  carouselUnconventionalRepublishTID,
    37  			ExpectedResult: true,
    38  		},
    39  		"carousel generated message should be ignored": {
    40  			TransactionID:  carouselGeneratedTID,
    41  			ExpectedResult: true,
    42  		},
    43  	}
    44  
    45  	for name, test := range tests {
    46  		t.Run(name, func(t *testing.T) {
    47  			h := kafkaMessageHandler{}
    48  			kafkaMessage := kafka.FTMessage{
    49  				Headers: map[string]string{
    50  					"X-Request-Id": test.TransactionID,
    51  				},
    52  			}
    53  
    54  			got := h.isIgnorableMessage(kafkaMessage)
    55  
    56  			if got != test.ExpectedResult {
    57  				t.Fatalf("expected %v, got %v", test.ExpectedResult, got)
    58  			}
    59  		})
    60  	}
    61  }
    62  
    63  func TestTestIsIgnorableMessage_SyntheticE2ETest(t *testing.T) {
    64  	e2eTestUUIDs := []string{"e4d2885f-1140-400b-9407-921e1c7378cd"}
    65  	log := logger.NewUPPLogger("publish-availability-monitor", "INFO")
    66  
    67  	mh := NewKafkaMessageHandler(nil, nil, nil, nil, nil, e2eTestUUIDs, log)
    68  	kmh := mh.(*kafkaMessageHandler)
    69  
    70  	kafkaMessage := kafka.FTMessage{
    71  		Headers: map[string]string{
    72  			"X-Request-Id": syntheticTID,
    73  		},
    74  	}
    75  
    76  	assert.Equal(t, false, kmh.isIgnorableMessage(kafkaMessage))
    77  }
    78  
    79  func TestUnmarshalContent_InvalidMessageMissingHeader_Error(t *testing.T) {
    80  	h := kafkaMessageHandler{}
    81  	if _, err := h.unmarshalContent(invalidMessageWrongHeader); err == nil {
    82  		t.Error("Expected failure, but message with missing system ID successfully unmarshalled!")
    83  	}
    84  }
    85  
    86  func TestUnmarshalContent_InvalidMessageWrongSystemId_Error(t *testing.T) {
    87  	h := kafkaMessageHandler{}
    88  	if _, err := h.unmarshalContent(invalidMessageWrongSystemID); err == nil {
    89  		t.Error("Expected failure, but message with wrong system ID successfully unmarshalled!")
    90  	}
    91  }
    92  
    93  func TestUnmarshalContent_ValidVideoMessage(t *testing.T) {
    94  	testCases := []struct {
    95  		videoMessage kafka.FTMessage
    96  	}{
    97  		{validVideoMsg},
    98  		{validVideoMsg2},
    99  	}
   100  
   101  	h := kafkaMessageHandler{}
   102  	log := logger.NewUPPLogger("test", "PANIC")
   103  
   104  	for _, testCase := range testCases {
   105  		resultContent, err := h.unmarshalContent(testCase.videoMessage)
   106  		if err != nil {
   107  			t.Errorf("Expected success, but error occurred [%v]", err)
   108  			return
   109  		}
   110  		valRes := resultContent.Validate("", "", "", "", log)
   111  		assert.False(t, valRes.IsMarkedDeleted, "Expected published content.")
   112  	}
   113  }
   114  
   115  func TestUnmarshalContent_ValidDeletedVideoMessage(t *testing.T) {
   116  	h := kafkaMessageHandler{}
   117  	resultContent, err := h.unmarshalContent(validDeleteVideoMsg)
   118  	if err != nil {
   119  		t.Errorf("Expected success, but error occurred [%v]", err)
   120  		return
   121  	}
   122  	log := logger.NewUPPLogger("test", "PANIC")
   123  
   124  	valRes := resultContent.Validate("", "", "", "", log)
   125  	assert.True(t, valRes.IsMarkedDeleted, "Expected deleted content.")
   126  }
   127  
   128  func TestUnmarshalContent_InvalidVideoMessage(t *testing.T) {
   129  	h := kafkaMessageHandler{}
   130  	resultContent, err := h.unmarshalContent(invalidVideoMsg)
   131  	if err != nil {
   132  		t.Errorf("Expected success, but error occurred [%v]", err)
   133  		return
   134  	}
   135  	log := logger.NewUPPLogger("test", "PANIC")
   136  
   137  	valRes := resultContent.Validate("", "", "", "", log)
   138  	assert.False(t, valRes.IsValid, "Expected invalid content.")
   139  }
   140  
   141  func TestUnmarshalContent_VideoBinaryContentSet(t *testing.T) {
   142  	h := kafkaMessageHandler{}
   143  	resultContent, err := h.unmarshalContent(validVideoMsg)
   144  	assert.NoError(t, err)
   145  
   146  	video, ok := resultContent.(content.Video)
   147  	assert.True(t, ok)
   148  
   149  	assert.Equal(t, []byte(validVideoMsg.Body), video.BinaryContent)
   150  }
   151  
   152  func TestUnmarshalContent_GenericContent(t *testing.T) {
   153  	h := kafkaMessageHandler{}
   154  
   155  	resultContent, err := h.unmarshalContent(validGenericContentMessage)
   156  	assert.NoError(t, err)
   157  
   158  	genericContent, ok := resultContent.(content.GenericContent)
   159  	assert.True(t, ok)
   160  
   161  	assert.Equal(t, "077f5ac2-0491-420e-a5d0-982e0f86204b", genericContent.UUID)
   162  	assert.Equal(t, validGenericContentMessage.Headers["Content-Type"], genericContent.Type)
   163  	assert.Equal(t, []byte(validGenericContentMessage.Body), genericContent.BinaryContent)
   164  	assert.False(t, genericContent.Deleted)
   165  }
   166  
   167  func TestUnmarshalContent_DeletedGenericContent(t *testing.T) {
   168  	h := kafkaMessageHandler{}
   169  
   170  	resultContent, err := h.unmarshalContent(validDeletedGenericContentMessage)
   171  	assert.NoError(t, err)
   172  
   173  	genericContent, ok := resultContent.(content.GenericContent)
   174  	assert.True(t, ok)
   175  
   176  	assert.Equal(t, "077f5ac2-0491-420e-a5d0-982e0f86204b", genericContent.GetUUID())
   177  	assert.Equal(t, validDeletedGenericContentMessage.Headers["Content-Type"], genericContent.GetType())
   178  	assert.Equal(t, []byte(validDeletedGenericContentMessage.Body), genericContent.BinaryContent)
   179  	assert.True(t, genericContent.Deleted)
   180  }
   181  
   182  func TestUnmarshalContent_GenericContent_Audio(t *testing.T) {
   183  	h := kafkaMessageHandler{}
   184  
   185  	resultContent, err := h.unmarshalContent(validGenericAudioMessage)
   186  	assert.NoError(t, err)
   187  
   188  	genericContent, ok := resultContent.(content.GenericContent)
   189  	assert.True(t, ok)
   190  
   191  	assert.Equal(t, "be003650-6c8f-4665-8640-9cbf292bb580", genericContent.UUID)
   192  	assert.Equal(t, validGenericAudioMessage.Headers["Content-Type"], genericContent.Type)
   193  	assert.Equal(t, []byte(validGenericAudioMessage.Body), genericContent.BinaryContent)
   194  }
   195  
   196  var invalidMessageWrongHeader = kafka.FTMessage{
   197  	Headers: map[string]string{
   198  		"Foobar-System-Id": "http://cmdb.ft.com/systems/cct",
   199  	},
   200  	Body: "{}",
   201  }
   202  var invalidMessageWrongSystemID = kafka.FTMessage{
   203  	Headers: map[string]string{
   204  		"Origin-System-Id": "web-foobar",
   205  	},
   206  	Body: "{}",
   207  }
   208  
   209  var validVideoMsg = kafka.FTMessage{
   210  	Headers: map[string]string{
   211  		"Origin-System-Id": "http://cmdb.ft.com/systems/next-video-editor",
   212  	},
   213  	Body: `{
   214  		"id": "e28b12f7-9796-3331-b030-05082f0b8157"
   215  	}`,
   216  }
   217  
   218  var validVideoMsg2 = kafka.FTMessage{
   219  	Headers: map[string]string{
   220  		"Origin-System-Id": "http://cmdb.ft.com/systems/next-video-editor",
   221  	},
   222  	Body: `{
   223  		"id": "e28b12f7-9796-3331-b030-05082f0b8157",
   224  		"deleted": false
   225  	}`,
   226  }
   227  
   228  var validDeleteVideoMsg = kafka.FTMessage{
   229  	Headers: map[string]string{
   230  		"Origin-System-Id": "http://cmdb.ft.com/systems/next-video-editor",
   231  	},
   232  	Body: `{
   233  		"id": "e28b12f7-9796-3331-b030-05082f0b8157",
   234  		"deleted": true
   235  	}`,
   236  }
   237  
   238  var invalidVideoMsg = kafka.FTMessage{
   239  	Headers: map[string]string{
   240  		"Origin-System-Id": "http://cmdb.ft.com/systems/next-video-editor",
   241  	},
   242  	Body: `{
   243  		"uuid": "e28b12f7-9796-3331-b030-05082f0b8157",
   244  		"something_else": "something else"
   245  	}`,
   246  }
   247  
   248  var validGenericContentMessage = kafka.FTMessage{
   249  	Headers: map[string]string{
   250  		"Origin-System-Id": "http://cmdb.ft.com/systems/cct",
   251  		"X-Request-Id":     "tid_0123wxyz",
   252  		"Content-Type":     "application/vnd.ft-upp-article-internal",
   253  	},
   254  	Body: `{
   255  		"uuid": "077f5ac2-0491-420e-a5d0-982e0f86204b",
   256  		"title": "A title",
   257  		"type": "Article",
   258  		"byline": "A byline",
   259  		"identifiers": [
   260  		  {
   261  			"authority": "an authority",
   262  			"identifierValue": "some identifier value"
   263  		  },
   264  		  {
   265  			"authority": "another authority",
   266  			"identifierValue": "some other identifier value"
   267  		  }
   268  		],
   269  		"publishedDate": "2014-12-23T20:45:54.000Z",
   270  		"firstPublishedDate": "2014-12-22T20:45:54.000Z",
   271  		"bodyXML": "<body>Lorem ipsum</body>",
   272  		"editorialDesk": "some string editorial desk identifier",
   273  		"description": "Some descriptive explanation for this content",
   274  		"mainImage": "0000aa3c-0056-506b-2b73-ed90e21b3e64",
   275  		"standout": {
   276  		  "editorsChoice": false,
   277  		  "exclusive": false,
   278  		  "scoop": false
   279  		},
   280  		"webUrl": "http://some.external.url.com/content",
   281  		"canBeSyndicated" : "verify",
   282  		"accessLevel" : "premium",
   283  		"canBeDistributed": "no",
   284  		"someUnknownProperty" : " is totally fine, we don't validate for unknown fields/properties"
   285  	  }`,
   286  }
   287  
   288  var validDeletedGenericContentMessage = kafka.FTMessage{
   289  	Headers: map[string]string{
   290  		"Origin-System-Id": "http://cmdb.ft.com/systems/cct",
   291  		"X-Request-Id":     "tid_0123wxyz",
   292  		"Content-Type":     "application/vnd.ft-upp-article-internal",
   293  	},
   294  	Body: `{
   295  		"uuid": "077f5ac2-0491-420e-a5d0-982e0f86204b",
   296  		"title": "A title",
   297  		"type": "Article",
   298  		"byline": "A byline",
   299  		"identifiers": [
   300  		  {
   301  			"authority": "an authority",
   302  			"identifierValue": "some identifier value"
   303  		  },
   304  		  {
   305  			"authority": "another authority",
   306  			"identifierValue": "some other identifier value"
   307  		  }
   308  		],
   309  		"publishedDate": "2014-12-23T20:45:54.000Z",
   310  		"firstPublishedDate": "2014-12-22T20:45:54.000Z",
   311  		"bodyXML": "<body>Lorem ipsum</body>",
   312  		"deleted": true
   313  	  }`,
   314  }
   315  
   316  var validGenericAudioMessage = kafka.FTMessage{
   317  	Headers: map[string]string{
   318  		"Origin-System-Id": "http://cmdb.ft.com/systems/next-video-editor",
   319  		"X-Request-Id":     "tid_0123wxyz",
   320  		"Content-Type":     "application/vnd.ft-upp-audio",
   321  	},
   322  	Body: `{
   323  		"title":"Is bitcoin a fraud?",
   324  		"byline":"News features and analysis from Financial Times reporters around the world. FT News in Focus is produced by Fiona Symon.",
   325  		"canBeSyndicated":"yes",
   326  		"firstPublishedDate":"2017-09-19T17:58:51.000Z",
   327  		"publishedDate":"2017-09-19T17:58:51.000Z",
   328  		"uuid":"be003650-6c8f-4665-8640-9cbf292bb580",
   329  		"type":"Audio",
   330  		"body":"<body><p>The value of bitcoin fell sharply last week after Jamie Dimon, head of JPMorgan Chase, suggested the digital currency craze would suffer the same fate as the tulip mania of the 17th century. Patrick Jenkins discusses whether he is right with the FT's Laura Noonan and Izabella Kaminska. Music by Kevin MacLeod</p></body>",
   331  		"mainImage":"56e9f220-6c64-4b6a-afcd-b57e1ceec807",
   332  		"identifiers":[  
   333  			{  
   334  				"authority":"http://www.acast.com/",
   335  				"identifierValue":"https://rss.acast.com/ft-news"
   336  			},
   337  			{  
   338  				"authority":"http://www.acast.com/",
   339  				"identifierValue":"https://www.acast.com/ft-news/isbitcoinafraud-"
   340  			},
   341  			{  
   342  				"authority":"http://api.ft.com/system/NEXT-VIDEO-EDITOR",
   343  				"identifierValue":"be003650-6c8f-4665-8640-9cbf292bb580"
   344  			}
   345  		],
   346  		"dataSource":[  
   347  			{  
   348  				"binaryUrl":"https://media.acast.com/ft-news/isbitcoinafraud-/media.mp3",
   349  				"duration":412000,
   350  				"mediaType":"audio/mpeg"
   351  			}
   352  		]
   353  	  }`,
   354  }