--[[----------------------------------------------------------------------------

WFCatCaptureDateTaskTest.lua

--------------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2017 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remains the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and are protected by all applicable
intellectual property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

----------------------------------------------------------------------------]]--

	-- WF.core.self_test
local WFRxTestCase = require 'WFRxTestCase'

	-- WF.oz_client.managed_catalog
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatCaptureDateTask = require 'WFCatCaptureDateTask'
local WFCatTaskManager = require 'WFCatTaskManager'
local WFCatAsset = require 'WFCatAsset'

	-- WF.core.utils
local KSIdGenerator = require 'KSIdGenerator'
local WFPlatformInfo = require 'WFPlatformInfo'

--------------------------------------------------------------------------------

if WFPlatformInfo.isAndroid then return {} end
	-- FIXME [jandrew 2018-03-22]: Disabling this test suite it's unreliable
	-- on Android.

--------------------------------------------------------------------------------

local createFakeWFCatalog = WFCatMockCatalog.createFakeWFCatalog

--==============================================================================

local WFCatCaptureDateTaskTest = {}

local kDefaultDescription = "WFCatTask"

local kInfinity = 1/0

local kNegativeInfinity = -kInfinity

local kNaN = 0 / 0
	
--------------------------------------------------------------------------------

local function addTestAsset( rxTest, catalog, localId, params )
	
	rxTest:expectSingleValue(

		catalog:docStore():bulkSetDocValue {
			{
				_id = KSIdGenerator.uuidInLowercaseHex(),
				_localId = localId,
				type = "asset",
				subtype = "image",
				_localOnly = {
					files = {
						original = {
							master = {
								path = string.format( 'local path %s', localId ),
							}
						}
					}
				},
				captureDate = params.maybeCaptureDate,
				xmp = {
					exif = {
						DateTimeOriginal = params.maybeDateTimeOriginal,
					},
					photoshop = {
						DateCreated = params.maybeDateCreated,
					},
					xmp = {
						CreateDate = params.maybeCreateDate,
					}
				},
			},
		},

		':ignore:' )
end

--------------------------------------------------------------------------------

--[[!
	Test the following case :
	-- a, a valid date time string
	-- b, a valid date time string with millisecond
		-- The new date time string should contain the millisecond, without loss the precision
		
	-- c, a valid date time string with timezone.
		-- The new date time string should contain the timezone, without loss the timezone info
		
	-- d, both 'xmp.exif.DateTimeOriginal' and 'xmp.photoshop.DateCreated' are nil.
		-- no updates for those two fields.
		
	-- f, 'xmp.xmp.CreateDate' is nil as well.
		-- the createDate will be set to the original capture date.
--]]

function WFCatCaptureDateTaskTest.rxTestEditCaptureDate( rxTest )
	
	local timeOut = 10
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '2017-08-15T15:22:59',
		maybeDateTimeOriginal = '2017-08-15T15:22:59',
		maybeDateCreated = '2017-08-15T15:22:59',
		maybeCreateDate = '2017-08-15T15:22:59',
	} )
	
	addTestAsset( rxTest, fakeWFCatalog, 2, {
		maybeCaptureDate = '2017-02-28T23:59:59.456',
		maybeDateTimeOriginal = '2017-02-28T23:59:59.456',
		maybeDateCreated = '2017-02-28T23:59:59.456',
		maybeCreateDate = '2017-02-28T23:59:59.456',
	} )
	
	addTestAsset( rxTest, fakeWFCatalog, 3, {
		maybeCaptureDate = '2017-12-31T23:59:59.456+05:30',
		maybeDateTimeOriginal = '2017-12-31T23:59:59.456+05:30',
		maybeDateCreated = '2017-12-31T23:59:59.456+05:30',
		maybeCreateDate = '2017-12-31T23:59:59.456+05:30',
	} )
	
	addTestAsset( rxTest, fakeWFCatalog, 4, {
		maybeCaptureDate = '2017-12-31T23:59:59.456+05:30',
		maybeDateTimeOriginal = nil,
		maybeDateCreated = nil,
		maybeCreateDate = '2017-12-31T23:59:59.456+05:30',
	} )
	
	addTestAsset( rxTest, fakeWFCatalog, 4, {
		maybeCaptureDate = '2017-12-31T23:59:59.456+05:30',
		maybeDateTimeOriginal = nil,
		maybeDateCreated = nil,
		maybeCreateDate = nil,
	} )
	
	local assetIds = { 1, 2, 3, 4, 5 }
	local numOfIds = #assetIds
	local timeDelta = 1
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	optUndoStateToken = 1
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			totalCount = numOfIds,
			undoToken = optUndoStateToken,
		},
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	} )
	
	taskObs:expectCompleted()
	
	-- Check the result data
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "2017-08-15T15:23:00",
			createDate = "2017-08-15T15:22:59",
			dateCreated = "2017-08-15T15:23:00",
			dateTimeOriginal = "2017-08-15T15:23:00",
		},
		{
			captureDateTime = '2017-03-01T00:00:00.456',
			createDate = '2017-02-28T23:59:59.456',
			dateCreated = '2017-03-01T00:00:00.456',
			dateTimeOriginal = '2017-03-01T00:00:00.456',
		},
		{
			captureDateTime = '2018-01-01T00:00:00.456+05:30',
			createDate = '2017-12-31T23:59:59.456+05:30',
			dateCreated = '2018-01-01T00:00:00.456+05:30',
			dateTimeOriginal = '2018-01-01T00:00:00.456+05:30',
		},
		{
			captureDateTime = '2018-01-01T00:00:00.456+05:30',
			createDate = '2017-12-31T23:59:59.456+05:30',
		},
		{
			captureDateTime = '2018-01-01T00:00:00.456+05:30',
			createDate = "2017-12-31T23:59:59.456+05:30",
		},
	}
end


--------------------------------------------------------------------------------

function WFCatCaptureDateTaskTest.rxTestEmptyCaptureDate( rxTest )
	
	local timeOut = 100
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	local localId = 1
	
	rxTest:expectSingleValue(

		fakeWFCatalog:docStore():bulkSetDocValue {
			{
				_id = KSIdGenerator.uuidInLowercaseHex(),
				_localId = localId,
				type = "asset",
				subtype = "image",
				_localOnly = {
					files = {
						original = {
							master = {
								path = string.format( 'local path %s', localId ),
							}
						}
					}
				},
			},
		},

		':ignore:' )
		
	local assetIds = { 1 }
	local numOfIds = #assetIds
	local timeDelta = 1
	local optUndoStateToken = nil
	
	local newDate = "2017-08-15T15:22:59.456+05:30"
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, newDate, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	optUndoStateToken = 2
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			totalCount = numOfIds,
			undoToken = optUndoStateToken,
		},
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	} )
	
	taskObs:expectCompleted()

	-- Check the result data
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "2017-08-15T15:22:59.456+05:30",
		},
	}

	-- 2), Add undo test case 
	local undoTask = WFCatCaptureDateTask.createCaptureDateTask( fakeWFCatalog, assetIds, nil, nil, optUndoStateToken )
	
	manager:addToQueue( undoTask )
	
	local undoTaskObs = rxTest:observe( undoTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectCompleted()
	
	-- 3) check the result
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "0000-00-00T00:00:00",
		},
	}

end

--------------------------------------------------------------------------------

--[[!
	Test when passing an infinity time delta,

	The capture date will not be updated. And error message will be returned.
--]]

function WFCatCaptureDateTaskTest.rxTestInfinityTimeDelta( rxTest )
	
	local timeOut = 5
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '2017-08-15T15:22:59',
		maybeDateTimeOriginal = '2017-08-15T15:22:59',
		maybeDateCreated = '2017-08-15T15:22:59',
		maybeCreateDate = '2017-08-15T15:22:59',
	} )
	
	local assetIds = { 1 }
	
	local timeDelta = kInfinity
	
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			errorMessage = "Invalid timeDelta",
		},
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	} )
	
	taskObs:expectCompleted()
	
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = '2017-08-15T15:22:59',
			createDate = '2017-08-15T15:22:59',
			dateCreated = '2017-08-15T15:22:59',
			dateTimeOriginal = '2017-08-15T15:22:59',
		},
	}
end


--------------------------------------------------------------------------------

--[[!
	Test when the original capture date string is malformed. 

	The capture date will be updated with a well-formed date string if possible.
--]]

function WFCatCaptureDateTaskTest.rxTestMalformedCaptureDate( rxTest )
	
	local timeOut = 10
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '1904-01-01T00:00Z',
		maybeDateTimeOriginal = '1904-01-01T00:00Z',
		maybeDateCreated = '1904-01-01T00:00Z',
		maybeCreateDate = '1904-01-01T00:00Z',
	} )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '1904-01-01T00Z',
		maybeDateTimeOriginal = '1904-01-01T00Z',
		maybeDateCreated = '1904-01-01T00Z',
		maybeCreateDate = '1904-01-01T00Z',
	} )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '1904-01-01',
		maybeDateTimeOriginal = '1904-01-01',
		maybeDateCreated = '1904-01-01',
		maybeCreateDate = '1904-01-01',
	} )
	
	local assetIds = { 1, 2, 3 }
	local numOfIds = #assetIds
	local timeDelta = 1
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	optUndoStateToken = 3
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			totalCount = numOfIds,
			undoToken = optUndoStateToken,
		},
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	} )
	
	taskObs:expectCompleted()
	
	-- Check the result data
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "1904-01-01T00:00:01Z",
			createDate = "1904-01-01T00:00Z",
			dateCreated = "1904-01-01T00:00:01Z",
			dateTimeOriginal = "1904-01-01T00:00:01Z",
		},
		{
			captureDateTime = "1904-01-01T00:00:01Z",
			createDate = "1904-01-01T00Z",
			dateCreated = "1904-01-01T00:00:01Z",
			dateTimeOriginal = "1904-01-01T00:00:01Z",
		},
		{
			captureDateTime = "1904-01-01T00:00:01",
			createDate = "1904-01-01",
			dateCreated = "1904-01-01T00:00:01",
			dateTimeOriginal = "1904-01-01T00:00:01",
		},
	}
end


--------------------------------------------------------------------------------

function WFCatCaptureDateTaskTest.rxTestMaybeCaptureDateIsEmpty( rxTest )
	
	local timeOut = 10
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	local testCaptureDate = '2017-08-15T15:22:59'
	local localId = 1
	
	rxTest:expectSingleValue(

		fakeWFCatalog:docStore():bulkSetDocValue {
			{
				_id = KSIdGenerator.uuidInLowercaseHex(),
				_localId = localId,
				type = "asset",
				subtype = "image",
				_localOnly = {
					files = {
						original = {
							master = {
								path = string.format( 'local path %s', localId ),
							}
						}
					}
				},
				xmp = {
					xmp = {
						CreateDate = testCaptureDate,
					}
				},
			},
		},

		':ignore:' )
		
	local assetIds = { 1 }
	local numOfIds = #assetIds
	local timeDelta = 1
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	optUndoStateToken = 4
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			totalCount = numOfIds,
			undoToken = optUndoStateToken,
		},
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	} )
	
	taskObs:expectCompleted()

	-- Check the result data
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "2017-08-15T15:23:00",
			createDate = "2017-08-15T15:22:59",
		},
	}
	
	-- 2), Add undo test case 
	local undoTask = WFCatCaptureDateTask.createCaptureDateTask( fakeWFCatalog, assetIds, nil, nil, optUndoStateToken )
	
	manager:addToQueue( undoTask )
	
	local undoTaskObs = rxTest:observe( undoTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectCompleted()
	
	-- 3) check the result
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			createDate = "2017-08-15T15:22:59",
		},
	}
	
end



--------------------------------------------------------------------------------

function WFCatCaptureDateTaskTest.rxTestMaybeXmpIsEmpty( rxTest )
	
	local timeOut = 10
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	local testCaptureDate = '2017-08-15T15:22:59'
	local localId = 1
	
	rxTest:expectSingleValue(

		fakeWFCatalog:docStore():bulkSetDocValue {
			{
				_id = KSIdGenerator.uuidInLowercaseHex(),
				_localId = localId,
				type = "asset",
				subtype = "image",
				_localOnly = {
					files = {
						original = {
							master = {
								path = string.format( 'local path %s', localId ),
							}
						}
					}
				},
				captureDate = testCaptureDate,
			},
		},

		':ignore:' )
		
	local assetIds = { 1 }
	local numOfIds = #assetIds
	local timeDelta = 1
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	optUndoStateToken = 5
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			totalCount = numOfIds,
			undoToken = optUndoStateToken,
		},
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	} )
	
	taskObs:expectCompleted()

	-- Check the result data
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "2017-08-15T15:23:00",
			createDate = "2017-08-15T15:22:59",
		},
	}
	
	-- 2), Add undo test case 
	local undoTask = WFCatCaptureDateTask.createCaptureDateTask( fakeWFCatalog, assetIds, nil, nil, optUndoStateToken )
	
	manager:addToQueue( undoTask )
	
	local undoTaskObs = rxTest:observe( undoTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectCompleted()
	
	-- 3) check the result
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = "2017-08-15T15:22:59",
		},
	}
	
end

--------------------------------------------------------------------------------

--[[!
	Test when passing an NaN time delta,

	The capture date will not be updated. And error message will be returned.
--]]

function WFCatCaptureDateTaskTest.rxTestNanTimeDelta( rxTest )
	
	local timeOut = 5
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '2017-08-15T15:22:59',
		maybeDateTimeOriginal = '2017-08-15T15:22:59',
		maybeDateCreated = '2017-08-15T15:22:59',
		maybeCreateDate = '2017-08-15T15:22:59',
	} )
	
	local assetIds = { 1 }
	
	local timeDelta = kNaN
	
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			errorMessage = "Invalid timeDelta",
		},
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	} )
	
	taskObs:expectCompleted()
	
	-- The capture date will not change due to the invalid time delta
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = '2017-08-15T15:22:59',
			createDate = '2017-08-15T15:22:59',
			dateCreated = '2017-08-15T15:22:59',
			dateTimeOriginal = '2017-08-15T15:22:59',
		},
	}
end

--------------------------------------------------------------------------------

--[[!
	Test when passing an negative infinity time delta,

	The capture date will not be updated. And error message will be returned.
--]]

function WFCatCaptureDateTaskTest.rxTestNegativeInfinityTimeDelta( rxTest )
	
	local timeOut = 5
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '2017-08-15T15:22:59',
		maybeDateTimeOriginal = '2017-08-15T15:22:59',
		maybeDateCreated = '2017-08-15T15:22:59',
		maybeCreateDate = '2017-08-15T15:22:59',
	} )
	
	local assetIds = { 1 }
	
	local timeDelta = kNegativeInfinity
	
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			errorMessage = "Invalid timeDelta",
		},
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	} )
	
	taskObs:expectCompleted()
	
	-- The capture date will not change due to the invalid time delta
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = '2017-08-15T15:22:59',
			createDate = '2017-08-15T15:22:59',
			dateCreated = '2017-08-15T15:22:59',
			dateTimeOriginal = '2017-08-15T15:22:59',
		},
	}
end


--------------------------------------------------------------------------------

function WFCatCaptureDateTaskTest.rxTestUndoEditCaptureDate( rxTest )
	
	local timeOut = 10
	
	rxTest:setTimeLimit( timeOut )
	
	local fakeWFCatalog = createFakeWFCatalog( rxTest )
	
	addTestAsset( rxTest, fakeWFCatalog, 1, {
		maybeCaptureDate = '2017-08-15T15:22:59',
		maybeDateTimeOriginal = '2016-08-15T15:22:59',
		maybeDateCreated = '2016-08-15T15:22:59',
		maybeCreateDate = '2016-08-15T15:22:59',
	} )
	
	
	-- 1) Edit capture date
	local assetIds = { 1 }
	local numOfIds = #assetIds
	
	local timeDelta = 1
	
	local optUndoStateToken = nil
	
	local testTask = WFCatCaptureDateTask.createCaptureDateTask( 
		fakeWFCatalog, assetIds, timeDelta, nil, optUndoStateToken )
		
	local manager = WFCatTaskManager.getCatTaskManager( fakeWFCatalog )
	
	manager:addToQueue( testTask )
	
	local taskObs = rxTest:observe( testTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	optUndoStateToken = 6
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = 1,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = 1,
		totalCount = 1,
	})
	
	taskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		extraInfo = {
			totalCount = 1,
			undoToken = optUndoStateToken,
		},
		percentComplete = 1,
		processedCount = 1,
		totalCount = 1,
	} )
	
	taskObs:expectCompleted()
	
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = '2017-08-15T15:23:00',
			createDate = '2016-08-15T15:22:59',
			dateCreated = '2017-08-15T15:23:00',
			dateTimeOriginal = '2017-08-15T15:23:00',
		},
	}
	
	-- 2) Undo edit
	
	local undoTask = WFCatCaptureDateTask.createCaptureDateTask( fakeWFCatalog, assetIds, nil, nil, optUndoStateToken )
	
	manager:addToQueue( undoTask )
	
	local undoTaskObs = rxTest:observe( undoTask:taskObservable()
		:map( function( data )
			return data
		end )
	)
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 0,
		processedCount = 0,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectDataWithinTime( timeOut, {
		description = kDefaultDescription,
		errorCount = 0,
		percentComplete = 1,
		processedCount = numOfIds,
		totalCount = numOfIds,
	})
	
	undoTaskObs:expectCompleted()
	
	-- 3) check the result
	rxTest:observe( WFCatAsset.collectInfoForAssetsFromDocStore( fakeWFCatalog, {
		assetIds = assetIds,
		captureDateTime = true,
		dateTimeOriginal = true,
		dateCreated = true,
		createDate = true,
	} ) )
	:expectData {
		{
			captureDateTime = '2017-08-15T15:22:59',
			createDate = '2016-08-15T15:22:59',
			dateCreated = '2016-08-15T15:22:59',
			dateTimeOriginal = '2016-08-15T15:22:59',
		},
	}
end

--------------------------------------------------------------------------------

return WFRxTestCase.wrapSuite( WFCatCaptureDateTaskTest )


