This commit is contained in:
Ross Reicks 2025-02-08 22:27:24 +08:00 committed by GitHub
commit 4020d7a112
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 18405 additions and 19 deletions

View file

@ -19,6 +19,7 @@ This [Github Action](https://github.com/features/actions) displays test results
- Java / [JUnit](https://junit.org/)
- JavaScript / [JEST](https://jestjs.io/) / [Mocha](https://mochajs.org/)
- Swift / xUnit
- Apex / [JSON](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_testing.htm)
For more information see [Supported formats](#supported-formats) section.
@ -341,6 +342,16 @@ Please update Mocha to version [v9.1.0](https://github.com/mochajs/mocha/release
Support for Swift test results in xUnit format is experimental - should work but it was not extensively tested.
</details>
<details>
<summary>apex-json (Experimental)</summary>
Support for [Salesforce Apex](https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_testing.htm)
```bash
sf apex test run --result-format json --wait 30 > test-results.json
```
</details>
## GitHub limitations
Unfortunately, there are some known issues and limitations caused by GitHub API:

View file

@ -0,0 +1,791 @@
![Tests failed](https://img.shields.io/badge/tests-735%20passed%2C%201%20failed-critical)
|Report|Passed|Failed|Skipped|Time|Coverage|
|:---|---:|---:|---:|---:|---:|
|fixtures/apex-json.json|735 ✅|1 ❌||26s|85%|
## ❌ <a id="user-content-r0" href="#r0">fixtures/apex-json.json</a>
**736** tests were completed in **26s** with **735** passed, **1** failed and **0** skipped.
|Test suite|Passed|Failed|Skipped|Time|Coverage|
|:---|---:|---:|---:|---:|---:|
|[Apex Tests](#r0s0)|735 ✅|1 ❌||26s|85%|
### ❌ <a id="user-content-r0s0" href="#r0s0">Apex Tests</a>
```
fflib_SecurityUtilsTest
❌ testSetup
Validation Errors While Saving Record(s)
✅ readonly_field_access
✅ readonly_objectAndField_access
✅ readonly_object_access
✅ sysadmin_objectAndField_access
fflib_StringBuilderTest
✅ testCommaDelimitedBuilder1
✅ testCommaDelimitedBuilder2
✅ testCommanDelimitedBuilderWithAlternativeDelimiter
✅ testCommanDelimitedBuilderWithAlternativeDelimiterAndPrefix
✅ testCommanDelimitedBuilderWithItemPrefix
✅ testFieldListBuilder
✅ testMultiCurrencyFieldListBuilder
✅ testfflib_StringBuilder1
✅ testfflib_StringBuilder2
fflib_ApplicationTest
✅ callingDomainFactoryShouldGiveRegisteredImplsAndMocks
✅ callingDomainFactoryWithContructorClassThatDoesNotSupportIConstructableShouldGiveException
✅ callingDomainFactoryWithGenericListShouldGiveException
✅ callingDomainFactoryWithIdsShouldGiveRegisteredImpls
✅ callingDomainFactoryWithInAccessableConstructorShouldGiveException
✅ callingDomainFactoryWithNoSObjectTypeShouldGiveException
✅ callingMockedUnitOfWorkWithCustomDML
✅ callingMockedUnitOfWorkWithCustomObjectTypesAndDML
✅ callingSelectorFactorySelectByIdWithEmptyListShouldGiveException
✅ callingSelectorFactorySelectByIdWithMixedIdTypeListShouldGiveException
✅ callingSelectorFactoryShouldGiveRegisteredImpls
✅ callingSelectoryFactorySelectByIdShouldReturnResults
✅ callingSelectoryFactorySselectByRelationshipPassRelatedIds
✅ callingServiceFactoryShouldGiveRegisteredImplsAndMockImpls
✅ callingUnitOfWorkFactoryShouldGivenStandardImplsAndMockImpls
✅ callingUnitOfWorkFactoryWithCustomTypesShouldGivenStandardImplsAndMockImpls
✅ callingUnitOfWorkWithCustomDML
✅ callingUnitOfWorkWithCustomObjectTypesAndDML
fflib_SObjectDomainTest
✅ itShouldReturnTheChangedRecordsBySObjectFields
✅ itShouldReturnTheChangedRecordsByStringFields
✅ testDisableTriggerEventsBehaviour
✅ testErrorLogging
✅ testGetChangedFieldsAsStrings
✅ testInsertValidationFailedWithoutDML
✅ testObjectSecurity
✅ testOnAfterUndeleteWithoutDML
✅ testOnBeforeDeleteWithoutDML
✅ testOnValidateBehaviorDefault
✅ testOnValidateBehaviorOld
✅ testRecursiveTriggerState
✅ testTriggerState
✅ testUpdateValidationFailedWithoutDML
✅ testValidationWithoutDML
fflib_SObjectSelectorTest
✅ testSetup
✅ testAddQueryFactorySubselect
✅ testAddQueryFactorySubselect2
✅ testAssertIsAccessible
✅ testCRUDOff
✅ testConfigureQueryFactoryFields
✅ testDefaultConfig
✅ testGetFieldListString
✅ testGetRelatedFieldListString
✅ testGetSObjectName
✅ testQueryLocatorById
✅ testSOQL
✅ testSOQL_defaultSorting
✅ testSelectSObjectsById
✅ testWithOrderingNullsLast
✅ testWithoutSorting
✅ toSOQL_When_PolymorphicSelectInMulticurrency_Expect_RelatedType
✅ toSOQL_When_PolymorphicSelect_Expect_RelatedType
✅ toSOQL_When_SystemModeAndChildRelationship_Expect_WellFormedSOQL
✅ toSOQL_When_SystemModeAndParentRelationshipAndDuplicateFields_Expect_WellFormedSOQL
✅ toSOQL_When_SystemModeAndUserCannnotReadField_Expect_Success
✅ toSOQL_When_SystemModeAndUserCannnotReadObject_Expect_Success
✅ toSOQL_When_SystemModePolymorphicSelect_Expect_RelatedType
✅ toSOQL_When_UserModeAndUserCannnotReadField_Expect_QueryException
✅ toSOQL_When_UserModeAndUserCannnotReadObject_Expect_QueryException
fflib_SObjectUnitOfWorkTest
✅ constructUserModeDML_When_AccessLevelSupplied_Expect_SameAccessLevel
✅ constructUserModeDML_When_DefaultConstructor_Expect_UserMode
✅ testAssertForEventSObjectType
✅ testAssertForEventSObjectType_ThrowExceptionOnNonEventObject
✅ testAssertForNonEventSObjectType
✅ testAssertForNonEventSObjectType_ThrowExceptionOnEventObject
✅ testAssertForSupportedSObjectType_throwExceptionOnUnsupportedType
✅ testDerivedUnitOfWork_CommitDMLFail
✅ testDerivedUnitOfWork_CommitDoWorkFail
✅ testDerivedUnitOfWork_CommitSuccess
✅ testRegisterDeleted
✅ testRegisterDirtyRecordsWithDirtyFields
✅ testRegisterDirtyRecordsWithDirtyFields_failing
✅ testRegisterDirty_ExpectReplacement
✅ testRegisterDirty_ThrowExceptionOnNewRecord
✅ testRegisterDirty_field
✅ testRegisterEmptyRecycleBin
✅ testRegisterNew_ThrowExceptionOnDirtyRecord
✅ testRegisterPermanentlyDeleted
✅ testRegisterUpsert
✅ testUnitOfWorkEmail
fflib_SObjectsTest
✅ itShouldClearTheField
✅ itShouldReturnFieldValues
✅ itShouldReturnRecordsIds
✅ itShouldReturnRecordsWithAllFieldValues
✅ itShouldReturnRecordsWithFieldValues
✅ itShouldReturnRecordsWithShippingCountry
✅ itShouldReturnRecordsWithoutAllFieldValues
✅ itShouldReturnRecordsWithoutFieldValues
✅ itShouldReturnTheDomainsType
✅ itShouldSetFieldValue
✅ itShouldSetFieldValueByCondition
✅ testDomainErrorLogging
✅ testErrorLogging
fflib_ObjectsTest
✅ itShouldContainAllTheObjects
✅ itShouldContainTheObject
✅ itShouldGetTheObjectType
✅ itShouldHaveAnEmptyDomain
✅ itShouldNotBeAnEmptyDomain
✅ itShouldNotContainTheObject
✅ itShouldNotContainTheObjects
✅ itShouldReturnTheCorrectType
fflib_QueryFactoryTest
✅ addChildQueriesWithChildRelationshipNoAccessibleCheck_fail
✅ addChildQueriesWithChildRelationshipNoAccessibleCheck_success
✅ addChildQueriesWithChildRelationshipObjCheckIsAccessible_success
✅ addChildQueriesWithChildRelationshipObj_success
✅ addChildQueriesWithChildRelationship_success
✅ addChildQueries_invalidChildRelationship
✅ addChildQueries_invalidChildRelationshipTooDeep
✅ addChildQueries_success
✅ addChildQuerySameRelationshipAgain_success
✅ checkFieldObjectReadSort_success
✅ checkFieldRead_fail
✅ checkObjectRead_fail
✅ deepCloneBasic
✅ deepCloneBasicNoChanges
✅ deepCloneSubquery
✅ deepCloneSubqueryNoChanges
✅ deterministic_toSOQL
✅ duplicateFieldSelection
✅ equalityCheck
✅ fieldSelections
✅ invalidCrossObjectField
✅ invalidFieldTests
✅ invalidField_nullToken
✅ invalidField_string
✅ invalidFields_noQueryField
✅ invalidFields_nullToken
✅ invalidFields_string
✅ nonReferenceField
✅ ordering
✅ queryFieldsNotEquals
✅ queryWith_noFields
✅ setOrdering_ReplacesPreviousOrderingsWithExpectedOrdering
✅ simpleFieldCondition
✅ simpleFieldSelection
✅ testSoql_allRows
✅ testSoql_unsortedSelectFields
fflib_SObjectDescribeTest
✅ FieldsMap
✅ GlobalDescribeMap
✅ NamespacedAttributeMap_implementations
✅ flushCache
✅ getAccountDescribes
✅ getDescribe_badInput
✅ rawGlobalDescribeCheck
✅ simpleAccountFieldDescribe
✅ simpleAccountFieldSetDescribe
✅ simpleAccountGetNameField
DomainProcessInjectionTest
✅ DomainProcessInjectionMethodTest
✅ accountInsertTwoCriteria
✅ accountUpdateTwoCriteria
✅ accountUpdateTwoCriteriaAsync
✅ verifyDomainProcessCoordinatorConstructorException
✅ verifyNewInstanceExceptionWithBadParams
✅ verifyNewInstanceExceptionWithNullParams
PlatformEventDistributorTest
✅ whenAT4DXImmediateMessagePublishedToEventBusTriggerHandlerProcessesEvent
✅ whenAT4DXMessagePublishedToEventBusTriggerHandlerProcessesEvent
✅ whenInvalidConsumerSuppliedExceptionThrown
✅ whenTriggerHandlerInvokedWithEventsWithoutCategoryOrEventNameFieldExceptionThrown
✅ whenTriggerHandlerInvokedWithMatchEventBus
✅ whenTriggerHandlerInvokedWithMatchEventBusAndCategory
✅ whenTriggerHandlerInvokedWithMatchEventBusAndCategoryAndEventName
✅ whenTriggerHandlerInvokedWithMatchEventBusAndEventName
✅ whenTriggerHandlerInvokedWithMatchEventBusWithAsynchronousSubscriber
fflib_QualifiedMethodTest
✅ equalsReturnsExpectedResults
✅ equalsReturnsExpectedResultsForHasDependentMocks
✅ hashCodeReturnsExpectedResults
✅ hashCodeReturnsExpectedResultsForHasDependentMocks
✅ toStringReturnsExpectedResult
di_PlatformCacheTest
✅ givenANewConfigSettingThenGetThatInstance
✅ givenCacheMapAddedThenGetKeys
✅ givenCachedBindingsClearThenGetEmpty
✅ givenDataInCachePartitionIsEnabledThenGetEmptyKeys
✅ givenDataInCachePartitionIsNotEnabledThenGetEmptyKeys
✅ givenDevNameAndSTypeThenGetHashAndKey
✅ givenInvalidDeveloperNameThenGetEmptyKeys
✅ givenInvalidSObjectTypeThenGetEmptyKeys
✅ givenKeyIndexNameThenGetKey
✅ givenLogMethodThenGetKeys
✅ givenNoDataInCachePartitionThenGetEmptyKeys
✅ givenNoPlatformCacheInstanceThenCreate
✅ givenPartitionNameSetThenGetNonNull
✅ givenPartitionTTLSetThenGetSeconds
✅ givenPlatformCacheConfigThenCreate
✅ givenReadOnlyAccessThenGetInstance
✅ givenStoringBindingIsTrueThenGet
✅ givenValidBindingThenAddBinding
✅ givenValidSTypeAndNameThenHash
✅ givenValidTSTypeAndNameThenHash
fflib_QualifiedMethodAndArgValuesTest
✅ equalsReturnsExpectedResults
ApplicationSObjectSelectorTest
✅ getSObjectFieldListTest
✅ selectionInjectionTest
ApplicationSObjectUnitOfWorkTest
✅ verifyApplicationSobjectUOWConstructorWithDML
✅ verifyGetDeletedRecordsByType
✅ verifyRegisterDirtyWithParentRecord
✅ verifyRegisterEmails
✅ verifyRegisterNewWithParentRecord
✅ verifyRegisterSingleRecordReturnDirtyRecordsByType
✅ verifyRegisterSingleRecordReturnsNewRecordsByType
✅ verifyRegisteredRecordListReturnDirtyRecordsByType
✅ verifyRegisteredRecordListReturnsNewRecordsByType
fflib_MethodArgValuesTest
✅ equalsReturnsExpectedResults
✅ hashCodeReturnsExpectedResults
fflib_MatcherDefinitionsTest
✅ constructDatetimeAfter_WithNullFromDatetime_ThrowsException
✅ constructDatetimeAfter_WithNullInclusive_ThrowsException
✅ constructDatetimeBefore_WithNullInclusive_ThrowsException
✅ constructDatetimeBefore_WithNullToDatetime_ThrowsException
✅ constructDatetimeBetween_WithNullFromDatetime_ThrowsException
✅ constructDatetimeBetween_WithNullInclusiveFrom_ThrowsException
✅ constructDatetimeBetween_WithNullInclusiveTo_ThrowsException
✅ constructDatetimeBetween_WithNullToDatetime_ThrowsException
✅ constructDecimalBetween_WithNullInclusiveLower_ThrowsException
✅ constructDecimalBetween_WithNullInclusiveUpper_ThrowsException
✅ constructDecimalBetween_WithNullLower_ThrowsException
✅ constructDecimalBetween_WithNullUpper_ThrowsException
✅ constructDecimalLessThan_WithNullInclusive_ThrowsException
✅ constructDecimalLessThan_WithNullToMatch_ThrowsException
✅ constructDecimalMoreThan_WithNullInclusive_ThrowsException
✅ constructDecimalMoreThan_WithNullToMatch_ThrowsException
✅ constructEq_WithNullArg_ThrowsException
✅ constructFieldSetEquivalentTo_WithNullFieldSet_ThrowsException
✅ constructRefEq_WithNullArg_ThrowsException
✅ constructSObjectOfType_WithNullArg_ThrowsException
✅ constructSObjectWithId_WithNullArg_ThrowsException
✅ constructSObjectWithName_WithNullArg_ThrowsException
✅ constructSObjectWith_WithEmptyArg_ThrowsException
✅ constructSObjectWith_WithNullArg_ThrowsException
✅ constructSObjectsWith_WithNullArg_ThrowsException
✅ constructStringContains_WithNullArg_ThrowsException
✅ constructStringEndsWith_WithNullArg_ThrowsException
✅ constructStringMatches_WithNullArg_ThrowsException
✅ constructStringStartsWith_WithNullArg_ThrowsException
✅ whenAnyBooleanMatchesShouldReturnCorrectResults
✅ whenAnyBooleanToStringReturnsExpectedString
✅ whenAnyDateMatchesShouldReturnCorrectResults
✅ whenAnyDateToStringReturnsExpectedString
✅ whenAnyDatetimeMatchesShouldReturnCorrectResults
✅ whenAnyDatetimeToStringReturnsExpectedString
✅ whenAnyDecimalMatchesShouldReturnCorrectResults
✅ whenAnyDecimalToStringReturnsExpectedString
✅ whenAnyDoubleMatchesShouldReturnCorrectResults
✅ whenAnyDoubleToStringReturnsExpectedString
✅ whenAnyFieldSetMatchesShouldReturnCorrectResults
✅ whenAnyFieldSetToStringReturnsExpectedString
✅ whenAnyIdMatchesShouldReturnCorrectResults
✅ whenAnyIdToStringReturnsExpectedString
✅ whenAnyIntegerMatchesShouldReturnCorrectResults
✅ whenAnyIntegerToStringReturnsExpectedString
✅ whenAnyListMatchesShouldReturnCorrectResults
✅ whenAnyListToStringReturnsExpectedString
✅ whenAnyLongMatchesShouldReturnCorrectResults
✅ whenAnyLongToStringReturnsExpectedString
✅ whenAnyObjectMatchesShouldReturnCorrectResults
✅ whenAnyObjectToStringReturnsExpectedString
✅ whenAnySObjectFieldMatchesShouldReturnCorrectResults
✅ whenAnySObjectFieldToStringReturnsExpectedString
✅ whenAnySObjectMatchesShouldReturnCorrectResults
✅ whenAnySObjectToStringReturnsExpectedString
✅ whenAnySObjectTypeMatchesShouldReturnCorrectResults
✅ whenAnySObjectTypeToStringReturnsExpectedString
✅ whenAnyStringMatchesShouldReturnCorrectResults
✅ whenAnyStringToStringReturnsExpectedString
✅ whenCombinedMatcherToStringReturnsExpectedString
✅ whenCombinedMatchesWithAllExpressionShouldReturnCorrectResults
✅ whenCombinedMatchesWithAtLeastOneExpressionShouldReturnCorrectResults
✅ whenCombinedMatchesWithNoneExpressionShouldReturnCorrectResults
✅ whenConstructingCombinedWithEmptyInternalMatchersShouldThrowException
✅ whenConstructingCombinedWithNullConnectiveExpressionShouldThrowException
✅ whenConstructingCombinedWithNullInternalMatchersShouldThrowException
✅ whenDatetimeAfterMatchesWithInclusiveShouldReturnCorrectResults
✅ whenDatetimeAfterMatchesWithoutInclusiveShouldReturnCorrectResults
✅ whenDatetimeAfterWithInclusiveToStringReturnsExpectedString
✅ whenDatetimeAfterWithNotInclusiveToStringReturnsExpectedString
✅ whenDatetimeBeforeMatchesWithInclusiveShouldReturnCorrectResults
✅ whenDatetimeBeforeMatchesWithoutInclusiveShouldReturnCorrectResults
✅ whenDatetimeBeforeWithInclusiveToStringReturnsExpectedString
✅ whenDatetimeBeforeWithNotInclusiveToStringReturnsExpectedString
✅ whenDatetimeBetweenMatchesWithInclusiveFromWithoutInclusiveToShouldReturnCorrectResults
✅ whenDatetimeBetweenMatchesWithInclusiveToWithoutInclusiveFromShouldReturnCorrectResults
✅ whenDatetimeBetweenWithInclusiveToStringReturnsExpectedString
✅ whenDatetimeBetweenWithNotInclusiveToStringReturnsExpectedString
✅ whenDecimalBetweenMatchesShouldReturnCorrectResults
✅ whenDecimalBetweenToStringReturnsExpectedString
✅ whenDecimalLessThanMatchesShouldReturnCorrectResults
✅ whenDecimalLessThanToStringReturnsExpectedString
✅ whenDecimalMoreThanMatchesShouldReturnCorrectResults
✅ whenDecimalMoreThanToStringReturnsExpectedString
✅ whenEqMatchesShouldReturnCorrectResults
✅ whenEqToStringShouldReturnExpectedString
✅ whenFieldSetEquivalentToMatchesShouldReturnCorrectResults
✅ whenFieldSetEquivalentToToStringReturnsExpectedString
✅ whenFieldSetEquivalentToWithoutFieldSetShouldNeverMatch
✅ whenIsBlankWithMatchesShouldReturnCorrectResults
✅ whenIsNotBlankWithMatchesShouldReturnCorrectResults
✅ whenIsNotNullMatchesShouldReturnCorrectResults
✅ whenIsNotNullToStringReturnsExpectedString
✅ whenIsNullMatchesShouldReturnCorrectResults
✅ whenIsNullToStringReturnsExpectedString
✅ whenJSONExceptionOccursStringifyShouldReturnsObjectToString
✅ whenListContainsMatchesShouldReturnCorrectResults
✅ whenListContainsToStringReturnsExpectedString
✅ whenListIsEmptyMatchesShouldReturnCorrectResults
✅ whenListIsEmptyToStringReturnsExpectedString
✅ whenRefEqMatchesShouldReturnCorrectResults
✅ whenRefEqToStringReturnsExpectedString
✅ whenSObjectOfTypeMatchesShouldReturnCorrectResults
✅ whenSObjectOfTypeToStringReturnsExpectedString
✅ whenSObjectWithIdMatchesShouldReturnCorrectResults
✅ whenSObjectWithIdToStringReturnsExpectedString
✅ whenSObjectWithMatchesShouldReturnCorrectResults
✅ whenSObjectWithNameMatchesShouldReturnCorrectResults
✅ whenSObjectWithNameToStringReturnsExpectedString
✅ whenSObjectWithToStringReturnsExpectedString
✅ whenSObjectsInAnyOrderWithMatchesShouldReturnCorrectResults
✅ whenSObjectsWithDifferentArityMatchesShouldReturnFalse
✅ whenSObjectsWithInOrderMatchesShouldReturnCorrectResults
✅ whenSObjectsWithToStringReturnsExpectedString
✅ whenStringContainsMatchesShouldReturnCorrectResults
✅ whenStringContainsToStringReturnsExpectedStrings
✅ whenStringEndsWithMatchesShouldReturnCorrectResults
✅ whenStringEndsWithToStringReturnsExpectedStrings
✅ whenStringIsBlankToStringReturnsExpectedStrings
✅ whenStringIsNotBlankToStringReturnsExpectedStrings
✅ whenStringMatchesMatchesShouldReturnCorrectResults
✅ whenStringMatchesToStringReturnsExpectedStrings
✅ whenStringStartsWithMatchesShouldReturnCorrectResults
✅ whenStringStartsWithToStringReturnsExpectedStrings
di_FlowTest
✅ givenNullInputWhenObjectCreatedThenSetInitialized
✅ givenStringValueWhenOutputThenStringAddedToSet
✅ givenVariableNameWhenRequiredThenValueAddedToSet
di_InjectorCMPFlowProxyControllerTest
✅ givenValueWhenGetInjectThenThrowException
di_InjectorComponentControllerTest
✅ givenApexPageComponentGetInjectorIsValid
✅ givenFlowNameWhenGetInjectorFlowProxyInstanceThenMethodCall
✅ givenLightningComponentGetBindingId
✅ givenWrongBindingNameValueWhenGetInjectThenThrowException
AbstractSelectorMethodInjectableTest
✅ verifyAbstractSelectorMethodInjection
AbstractSelectorQueryLocatorInjectblTest
✅ verifyAbstractSelectorQueryLocatorInjection
di_InjectorControllerTest
✅ givenStandardControllerWhenObjectCreatedThenConstructorCalled
di_InjectorTest
✅ givenBindingsWithAlternateObjectNameThenBindingIsReturned
✅ givenInjectorWithBindingsThenBindingIsReturned
✅ givenInstanceNameThenGetException
✅ givenInstanceThenGetThatInstance
✅ givenListOfModulesBindThenGetCount
✅ givenNoBindingsGetInstanceShouldThrowException
✅ givenNullParamterInGetInstanceThenThrowException
✅ givenNullSTypeParamterInGetInstanceThenThrowException
✅ test
✅ whenDeveloperNameIsEmptyThenGetInstanceShouldThrowException
ApplicationFactoryTest
✅ Application_Domain_Constructor2Test
✅ Application_Domain_ConstructorTest
✅ Application_Domain_MockDomainConstructor2Test
✅ Application_Domain_MockDomainConstructorTest
✅ Application_Selector_HappyPathTest
✅ Application_Selector_PrioritizationTest
✅ Application_Selector_SelectByIdHelperTest
✅ Application_Selector_SelectByRelationshipTest
✅ Application_Selector_SetMockTest
✅ Application_Service_HappyPathTest
✅ Application_Service_MockServiceTest
✅ Application_Service_MultiServiceTest
✅ Application_UnitOfWork_HappyPathTest
fflib_AnswerTest
✅ thatAnswerOnlyForTheMethodStubbedWithAnswer
✅ thatAnswerOnlyForTheStubbedParameter
✅ thatAnswerToDifferentVoidMethods
✅ thatAnswerToVoidAndNotVoidMethods
✅ thatAnswerToVoidMethod
✅ thatAnswersWithException
✅ thatArgumentListEmptyForMethodWithNoArgument
✅ thatExceptionIsThrownWhenAccessNegativeIndexArgument
✅ thatExceptionIsThrownWhenAccessOutOfIndexArgument
✅ thatMethodsParametersAreAccessible
✅ thatMethodsParametersAreAccessibleWhenCalledWithMatchers
✅ thatMultipleAnswersAreHandled
✅ thatStoresMethodIntoInvocationOnMock
✅ thatStoresMockInstanceIntoInvocationOnMock
PlatformEventDistributorDIModuleTest
✅ whenPlatformEventSubscriptionConsumerBlankExceptionThrown
✅ whenPlatformEventSubscriptionCustomMetadataPresentVerifyForceDIBinding
✅ whenPlatformEventSubscriptionEventBusBlankExceptionThrown
di_ModuleTest
✅ givenBadBindingTypeThenGetModuleException
✅ givenBindingInModuleWhenSetTypeThenGetModule
✅ givenModuleWhenSettingValuesThenGet
fflib_SystemTest
✅ assertEquals_WithCombinedMatcher_ShouldPass
✅ assertEquals_WithCustomMessage_WithCombinedMatcher_ShouldPass
✅ assertEquals_WithCustomMessage_WithMatch_ShouldPass
✅ assertEquals_WithCustomMessage_WithMismatch_ShouldThrowException
✅ assertEquals_WithCustomMessage_WithNoMatchers_ShouldThrowException
✅ assertEquals_WithCustomMessage_WithTooManyMatchers_ShouldThrowException
✅ assertEquals_WithMatch_ShouldPass
✅ assertEquals_WithMismatch_ShouldThrowException
✅ assertEquals_WithNoMatchers_ShouldThrowException
✅ assertEquals_WithTooManyMatchers_ShouldThrowException
fflib_ArgumentCaptorTest
✅ thatArgumentValueIsCaptured
✅ thatArgumentValueIsCapturedWithInOrderVerification
✅ thatCanHandleMultipleCapturesInOneMethodCall
✅ thatCanHandleMultipleCapturesInOneMethodCallWithInOrderVerification
✅ thatCanPerformFurtherAssertionsOnCapturedArgumentValue
✅ thatCanPerformFurtherAssertionsOnCapturedArgumentValueWithInOrderVerification
✅ thatCaptureAllArguments
✅ thatCaptureAllArgumentsForTheVerifiedMethods
✅ thatCaptureAllArgumentsForTheVerifiedMethodsWithInOrderVerification
✅ thatCaptureAllArgumentsFromMultipleMethods
✅ thatCaptureAllArgumentsFromMultipleMethodsWithInOrderVerification
✅ thatCaptureAllArgumentsWithInOrderVerification
✅ thatCaptureAllArgumentswhenMethodIsCalledWithTheSameArgument
✅ thatCaptureArgumentFromRequestedParameter
✅ thatCaptureArgumentFromRequestedParameterWithInOrderVerification
✅ thatCaptureArgumentOnlyFromVerifiedMethod
✅ thatCaptureArgumentOnlyFromVerifiedMethodWithInOrderVerification
✅ thatCaptureLastArgument
✅ thatCaptureLastArgumentWithInOrderVerification
✅ thatCaptureOnlyMethodsThatMatchesWithOtherMatcherAsWell
✅ thatCaptureOnlyMethodsThatMatchesWithOtherMatcherAsWellWithInOrderVerification
✅ thatDoesNotCaptureAnythingWhenCaptorIsWrappedInAMatcher
✅ thatDoesNotCaptureAnythingWhenCaptorIsWrappedInAMatcherWithInOrderVerification
✅ thatDoesNotCaptureIfNotVerified
✅ thatDoesNotCaptureIfNotVerifiedWithInOrderVerification
fflib_ApexMocksUtilsTest
✅ makeRelationship_GenericOverload_ReturnsObjectsWithRelationFieldSet
✅ makeRelationship_GenericOverload_ThrowsErrorOnInvalidChildType
✅ makeRelationship_GenericOverload_ThrowsErrorOnInvalidFieldName
✅ makeRelationship_GenericOverload_ThrowsErrorOnInvalidParentType
✅ makeRelationship_returnsObjectsWithRelationFieldSet
✅ setReadOnlyFields_CreatedByIdSetToCurrentUserId_IdFieldSetSuccessfully
✅ setReadOnlyFields_IsDeletedSetOnAccount_BooleanFieldSetSuccessfully
✅ setReadOnlyFields_LastReferencedDateSetOnAccount_DateTimeFieldSetSuccessfully
✅ setReadOnlyFields_PolymorphicRelationJoin_FieldSetSuccessfully
fflib_ApexMocksTest
✅ stubAndVerifyMethodCallsWithNoArguments
✅ thatExceptionIsthrownWhenReturnMultiPassEmptyList
✅ thatExceptionIsthrownWhenReturnMultiPassNullList
✅ thatExceptionIsthrownWhenStubbingIsNotDone
✅ thatExceptionIsthrownWhenThrowMultiPassEmptyList
✅ thatExceptionIsthrownWhenThrowMultiPassNullList
✅ thatMultipleInstancesCanBeMockedDependently
✅ thatMultipleInstancesCanBeMockedIndependently
✅ thatMultipleVoidMethodsThrowsMultipleExceptions
✅ thatNullCanBeUsedAsExceptionvalue
✅ thatNullCanBeUsedAsReturnValue
✅ thatStubbingCanBeChainedFirstValueThenException
✅ thatStubbingMultipleMethodsCanBeChainedFirstExceptionThenValue
✅ thatStubbingMultipleMethodsCanBeChainedFirstValueThenException
✅ thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithMultiExceptions
✅ thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithMultiValue
✅ thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithSingleException
✅ thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithSingleValue
✅ thatStubbingMultipleTimesOverridePreviousThenReturnWithMultiExceptions
✅ thatStubbingMultipleTimesOverridePreviousThenReturnWithMultiValues
✅ thatStubbingMultipleTimesOverridePreviousThenReturnWithSingleException
✅ thatStubbingMultipleTimesOverridePreviousThenReturnWithSingleValue
✅ thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithMultiExceptions
✅ thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithMultiValue
✅ thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithSingleException
✅ thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithSingleValue
✅ thatStubbingMultipleTimesOverridePreviousThenThrowWithMultiExceptions
✅ thatStubbingMultipleTimesOverridePreviousThenThrowWithMultiValues
✅ thatStubbingMultipleTimesOverridePreviousThenThrowWithSingleException
✅ thatStubbingMultipleTimesOverridePreviousThenThrowWithSingleValue
✅ thatStubbingMutipleTimesVoidMethodThrowsMultipleExceptionsOverride
✅ thatStubbingMutipleTimesVoidMethodThrowsMultipleExceptionsOverrideWithSingleException
✅ thatStubbingReturnsAndThrowsDifferentValuesAndExceptionsForDifferentCalls
✅ thatStubbingReturnsDifferentValuesForDifferentCalls
✅ thatStubbingReturnsDifferentValuesForDifferentCallsAndRepeatLastValuesForFurtherCalls
✅ thatStubbingThrowsAndReturnsDifferentExceptionsAndValuesForDifferentCalls
✅ thatStubbingThrowsDifferentExceptionsForDifferentCalls
✅ thatStubbingThrowsDifferentExceptionsForDifferentCallsAndRepeatLastExceptionForFurtherCalls
✅ thatToStringReturnsSimpleStringValue
✅ thatVoidMethodThrowsMultipleExceptions
✅ verifyMethodCallWhenNoCallsBeenMadeForType
✅ verifyMethodCallsWithSameNameButDifferentArgumentTypes
✅ verifyMethodNotCalled
✅ verifyMultipleMethodCallsWithDifferentSingleArgument
✅ verifyMultipleMethodCallsWithSameSingleArgument
✅ verifySingleMethodCallWithMultipleArguments
✅ verifySingleMethodCallWithNoArguments
✅ verifySingleMethodCallWithSingleArgument
✅ whenMockIsGeneratedCanStubVerify
✅ whenMockIsGeneratedCanVerify
✅ whenSetDoThrowWhenExceptionsValuesAreSet
✅ whenStubCallWithNoArgumentsShouldReturnStubbedValue
✅ whenStubCustomMatchersCanBeUsed
✅ whenStubExceptionSameMethodWithMatchersAndNonMatchersShouldStubInOrder
✅ whenStubExceptionTheExceptionShouldBeThrown
✅ whenStubExceptionWithMatchersShouldThrowException
✅ whenStubMultipleCallsWithMatchersShouldReturnExpectedValues
✅ whenStubMultipleCallsWithMultipleArgumentShouldReturnStubbedValues
✅ whenStubMultipleCallsWithSingleArgumentShouldReturnStubbedValues
✅ whenStubMultipleVoidMethodsWithExceptionsThenExceptionsShouldBeThrown
✅ whenStubNullConcreteArgValueCorrectValueIsReturned
✅ whenStubSameCallWithDifferentArgumentValueShouldReturnLastStubbedValue
✅ whenStubSameMethodWithMatchersAndNonMatchersShouldStubInOrder
✅ whenStubSingleCallWithNullReturnValueItShouldReturnNull
✅ whenStubSingleCallWithSingleArgumentShouldReturnStubbedValue
✅ whenStubVoidMethodWithExceptionAndCallMethodTwiceThenExceptionShouldBeThrownTwice
✅ whenStubVoidMethodWithExceptionThenExceptionShouldBeThrown
✅ whenStubWithMatcherAndNonMatcherArgumentsShouldThrowException
✅ whenVerifyCustomMatchersCanBeUsed
✅ whenVerifyMethodNeverCalledMatchersAreReset
✅ whenVerifyMultipleCallsWithMatchersShouldReturnCorrectMethodCallCounts
✅ whenVerifyWithCombinedMatchersShouldReturnCorrectMethodCallCounts
✅ whenVerifyWithMatcherAndNonMatcherArgumentsShouldThrowException
fflib_AnyOrderTest
✅ thatBetweenThrownExceptionIfCalledLessThanAtLeastNumberOfTimes
✅ thatBetweenThrownExceptionIfCalledLessThanAtLeastNumberOfTimesWithMatchers
✅ thatBetweenThrownExceptionIfCalledMoreThanAtMostNumberOfTimes
✅ thatBetweenThrownExceptionIfCalledMoreThanAtMostNumberOfTimesWithMatchers
✅ thatCustomMessageIsAdded
✅ thatThrownExceptionIfCalledLessThanAtLeastNumberOfTimes
✅ thatThrownExceptionIfCalledLessThanAtLeastNumberOfTimesWithMatchers
✅ thatThrownExceptionIfCalledLessThanAtLeastOnce
✅ thatThrownExceptionIfCalledLessThanAtLeastOnceNumberOfTimes
✅ thatThrownExceptionIfCalledLessThanAtLeastOnceNumberOfTimesWithMatchers
✅ thatThrownExceptionIfCalledLessThanAtLeastOnceWithMatchers
✅ thatThrownExceptionIfCalledMoreThanAtMostNumberOfTimes
✅ thatThrownExceptionIfCalledMoreThanAtMostNumberOfTimesWithMatchers
✅ thatVerifiesAtLeastNumberOfTimes
✅ thatVerifiesAtLeastNumberOfTimesWhenIsCalledMoreTimes
✅ thatVerifiesAtLeastNumberOfTimesWhenIsCalledMoreTimesWithMatchers
✅ thatVerifiesAtLeastNumberOfTimesWithMatchers
✅ thatVerifiesAtLeastOnce
✅ thatVerifiesAtLeastOnceNumberOfTimes
✅ thatVerifiesAtLeastOnceNumberOfTimesWhenIsCalledMoreTimes
✅ thatVerifiesAtLeastOnceNumberOfTimesWhenIsCalledMoreTimesWithMatchers
✅ thatVerifiesAtLeastOnceNumberOfTimesWithMatchers
✅ thatVerifiesAtLeastOnceWhenIsCalledMoreTimes
✅ thatVerifiesAtLeastOnceWhenIsCalledMoreTimesWithMatchers
✅ thatVerifiesAtLeastOnceWithMatchers
✅ thatVerifiesAtMostNumberOfTimes
✅ thatVerifiesAtMostNumberOfTimesWithMatchers
✅ thatVerifiesAtMostSameNumberOfTimes
✅ thatVerifiesAtMostSameNumberOfTimesWithMatchers
✅ thatVerifiesBetweenNumberOfTimes
✅ thatVerifiesBetweenNumberOfTimesWithMatchers
✅ thatVerifyNeverFailsWhenCalledMoreTimes
✅ thatVerifyNeverFailsWhenCalledMoreTimesWithMatchers
✅ thatVerifyTimesMethodFailsWhenCalledLessTimes
✅ thatVerifyTimesMethodFailsWhenCalledLessTimesWithMatchers
✅ thatVerifyTimesMethodFailsWhenCalledMoreTimes
✅ thatVerifyTimesMethodFailsWhenCalledMoreTimesWithMatchers
✅ verifyMethodCallWhenNoCallsBeenMadeForType
✅ verifyMethodNotCalled
✅ verifyMultipleMethodCallsWithSameSingleArgument
✅ verifyNeverMethodHasBeenNotCalledWithMatchers
✅ verifyNeverMethodHasNotBeenCalled
✅ verifySingleMethodCallWithMultipleArguments
✅ verifyTimesMethodHasBeenCalled
✅ verifyTimesMethodHasBeenCalledWithMatchers
✅ whenVerifyCustomMatchersCanBeUsed
✅ whenVerifyMethodNeverCalledMatchersAreReset
✅ whenVerifyMultipleCallsWithMatchersShouldReturnCorrectMethodCallCounts
✅ whenVerifyWithCombinedMatchersShouldReturnCorrectMethodCallCounts
di_BindingConfigWrapperTest
✅ givenBindingWrapperThenExtractAndValidate
✅ givenBindingWrapperWithBindingNameExpectDeveloperNameEqualsBindingName
✅ givenBindingWrapperWithMDTThenExtractAndValidate
di_BindingParamTest
✅ givenBooleansWhenGetParameterThenGetValues
✅ givenDateTimesWhenGetParameterThenGetValues
✅ givenDatesWhenGetParameterThenGetValues
✅ givenDecimalsWhenGetParameterThenGetValues
✅ givenNullInputWhenGetParameterThenGetNullValue
✅ givenStringsWhenGetParameterThenGetValues
✅ givenUnknownKeyWhenGetParameterThenGetNullValue
di_BindingTest
✅ givenApexBindingWhenGetInstanceThenInstance
✅ givenApexBindingWhenGetInstanceWithParamThenInstanceWithParam
✅ givenApexBindingWhenGetNewInstanceThenNewInstance
✅ givenApexBindingsWithDeveloperNamesWhenSortThenReturnSortedBindingsList
✅ givenApexBindingsWithSequenceAndWithoutObjectWhenSortThenReturnSortedBindingsList
✅ givenApexBindingsWithSequenceWhenSortThenReturnSortedBindingsList
✅ givenApexBindingsWithSobjectTypesWhenSortThenReturnSortedBindingsList
✅ givenIncorrectApexBindingWhenGetInstanceThenThrowException
✅ shouldConvertBindingToStringWhenObjectIsEmptyAndSequenceIsProvided
fflib_MatchTest
✅ allOfWith2ArgsRegistersCorrectMatcherType
✅ allOfWith3ArgsRegistersCorrectMatcherType
✅ allOfWith4ArgsRegistersCorrectMatcherType
✅ allOfWithEmptyArgsThrowsException
✅ allOfWithListArgsRegistersCorrectMatcherType
✅ allOfWithNoArgsThrowsException
✅ allOfWithoutRegisteringInnerMatchersThrowsException
✅ anyBooleanRegistersCorrectMatcherType
✅ anyDateRegistersCorrectMatcherType
✅ anyDatetimeRegistersCorrectMatcherType
✅ anyDecimalRegistersCorrectMatcherType
✅ anyDoubleRegistersCorrectMatcherType
✅ anyFieldSetRegistersCorrectMatcherType
✅ anyIdRegistersCorrectMatcherType
✅ anyIntegerRegistersCorrectMatcherType
✅ anyListRegistersCorrectMatcherType
✅ anyLongRegistersCorrectMatcherType
✅ anyObjectRegistersCorrectMatcherType
✅ anyOfWith2ArgsRegistersCorrectMatcherType
✅ anyOfWith3ArgsRegistersCorrectMatcherType
✅ anyOfWith4ArgsRegistersCorrectMatcherType
✅ anyOfWithListArgsRegistersCorrectMatcherType
✅ anySObjectFieldRegistersCorrectMatcherType
✅ anySObjectRegistersCorrectMatcherType
✅ anySObjectTypeRegistersCorrectMatcherType
✅ anyStringRegistersCorrectMatcherType
✅ dateAfterRegistersCorrectMatcherType
✅ dateBeforeRegistersCorrectMatcherType
✅ dateBetweenRegistersCorrectMatcherType
✅ datetimeAfterRegistersCorrectMatcherType
✅ datetimeBeforeRegistersCorrectMatcherType
✅ datetimeBetweenRegistersCorrectMatcherType
✅ decimalBetweenRegistersCorrectMatcherType
✅ decimalLessThanRegistersCorrectMatcherType
✅ decimalMoreThanRegistersCorrectMatcherType
✅ doubleBetweenRegistersCorrectMatcherType
✅ doubleLessThanRegistersCorrectMatcherType
✅ doubleMoreThanRegistersCorrectMatcherType
✅ eqBooleanRegistersCorrectMatcherType
✅ eqDateRegistersCorrectMatcherType
✅ eqDatetimeRegistersCorrectMatcherType
✅ eqDecimalRegistersCorrectMatcherType
✅ eqDoubleRegistersCorrectMatcherType
✅ eqIdRegistersCorrectMatcherType
✅ eqIntegerRegistersCorrectMatcherType
✅ eqListRegistersCorrectMatcherType
✅ eqLongRegistersCorrectMatcherType
✅ eqRegistersCorrectMatcherType
✅ eqSObjectFieldRegistersCorrectMatcherType
✅ eqSObjectTypeRegistersCorrectMatcherType
✅ eqStringRegistersCorrectMatcherType
✅ fieldSetEquivalentToRegistersCorrectMatcherType
✅ fieldSetEquivalentWithNullFieldSetThrowsException
✅ integerBetweenRegistersCorrectMatcherType
✅ integerLessThanRegistersCorrectMatcherType
✅ integerMoreThanRegistersCorrectMatcherType
✅ isNotNullRegistersCorrectMatcherType
✅ isNotRegistersCorrectMatcherType
✅ isNullRegistersCorrectMatcherType
✅ listContainsRegistersCorrectMatcherType
✅ listIsEmptyRegistersCorrectMatcherType
✅ longBetweenRegistersCorrectMatcherType
✅ longLessThanRegistersCorrectMatcherType
✅ longMoreThanRegistersCorrectMatcherType
✅ noneOfWith2ArgsRegistersCorrectMatcherType
✅ noneOfWith3ArgsRegistersCorrectMatcherType
✅ noneOfWith4ArgsRegistersCorrectMatcherType
✅ noneOfWithListArgsRegistersCorrectMatcherType
✅ refEqRegistersCorrectMatcherType
✅ sObjectOfTypeRegistersCorrectMatcherType
✅ sObjectWithIdRegistersCorrectMatcherType
✅ sObjectWithNameRegistersCorrectMatcherType
✅ sObjectWithRegistersCorrectMatcherType
✅ sObjectsWithMatchInOrderRegistersCorrectMatcherType
✅ sObjectsWithRegistersCorrectMatcherType
✅ stringContainsRegistersCorrectMatcherType
✅ stringEndsWithRegistersCorrectMatcherType
✅ stringIsBlankRegistersCorrectMatcherType
✅ stringIsNotBlankRegistersCorrectMatcherType
✅ stringMatchesRegistersCorrectMatcherType
✅ stringStartsWithRegistersCorrectMatcherType
✅ whenMatchesAllArgsWithDifferentSizeArgValuesAndMatchersThrowsException
✅ whenMatchesAllArgsWithManyMatchesReturnsTrue
✅ whenMatchesAllArgsWithManyMismatchesReturnsFalse
✅ whenMatchesAllArgsWithMatchesAndMismatchesReturnsFalse
✅ whenMatchesAllArgsWithNullMatchersThrowsException
✅ whenMatchesAllArgsWithNullMethodArgsArgValuesThrowsException
✅ whenMatchesAllArgsWithNullMethodArgsThrowsException
✅ whenMatchesAllArgsWithOneMatchReturnsTrue
✅ whenMatchesAllArgsWithOneMismatchReturnsFalse
✅ whenMatchesWithOneMatcherRegistersMatcher
✅ whenMatchesWithOneMatcherReturnsNull
✅ whenMatchesWithOneMatcherSetsMatchingToTrue
fflib_InheritorTest
✅ canInstantiateMultipleInterfaceInheritor
✅ canStubMultipleInterfaceInheritor
fflib_InOrderTest
✅ thatMixedVerificationDoNotInterfierWithOtherImplementationChecking
✅ thatStrictVerificationCanBeEnforced
✅ thatStrictVerificationCanBeEnforcedWithOldNotation
✅ thatStrictVerificationCanBeEnforcedWithOldNotationUsingDefaultTimesOne
✅ thatStrictVerificationCanBePerformed
✅ thatTimesOneIsTheDefaultVerification
✅ thatVerifyAtLeastConsumeAllTheInstances
✅ thatVerifyAtLeastConsumeAllTheInstancesForOnlyTheMethodVerified
✅ thatVerifyAtLeastConsumesAllTheInstances2
✅ thatVerifyAtLeastOnce
✅ thatVerifyAtLeastOnceConsumesAllTheInstances
✅ thatVerifyAtLeastOnceConsumesInstancesUntilLastMethodVerified
✅ thatVerifyAtLeastOnceThrowsErrorIfCalledLessTimes
✅ thatVerifyAtLeastPassWithMoreCallsThenAsserted
✅ thatVerifyAtLeastPassWithSameCallsOfAssertion
✅ thatVerifyAtLeastThrowsErrorIfCalledLessTimes
✅ thatVerifyAtMostThrowsExceptionBecauseNotImplemented
✅ thatVerifyBetweenThrowsExceptionBecauseNotImplemented
✅ thatVerifyInOrderAllTheMethodsCalled
✅ thatVerifyInOrderCallMethodWithMatches
✅ thatVerifyInOrderCallMethodWithMatchesFailsIfVerifyACallAlreadyInTheMatcher
✅ thatVerifyInOrderCallMethodWithMultipleMatches
✅ thatVerifyInOrderCallMethodWithMultipleMatchesMixed
✅ thatVerifyInOrderCallMethodWithMultipleMatchesMixedFailWhenMatcherHaveAlreadyVerifiedMethod
✅ thatVerifyInOrderCanHandleMixedInOrderInstance
✅ thatVerifyInOrderCanHandleMultipleMethodsCalls
✅ thatVerifyInOrderCanHandleMultipleMethodsCallsAndNotFailsIfVerifyCountIsGreaterThenExpected
✅ thatVerifyInOrderCanHandleMultipleMethodsCallsButFailsIfVerifyCountIsLessThenExpected
✅ thatVerifyInOrderCanHandleMultipleMocks
✅ thatVerifyInOrderCanSkipMethodsCalledUntilFindTheOneThatNeedsVerify
✅ thatVerifyInOrderDifferentMethodsCalledWithSameArguments
✅ thatVerifyInOrderDifferentMethodsCalledWithSameArgumentsDoubleCallFail
✅ thatVerifyInOrderDifferentMethodsCalledWithSameArgumentsOrderFail
✅ thatVerifyInOrderThrownExceptionIfVerifyMockInstanceNotInTheSet
✅ thatVerifyInOrderThrownExceptionWithCustomMessage
✅ thatVerifyNever
✅ thatVerifyNeverFailsWhenCalled
✅ thatVerifyNeverFailsWhenCalledWithMatchers
✅ thatVerifyNeverWithMatchers
✅ thatVerifyNoInteractionsFails
✅ thatVerifyNoInteractionsPass
✅ thatVerifyNoMoreInteractionsFails
✅ thatVerifyNoMoreInteractionsFailsWhenNoInteracionOccurs
✅ thatVerifyNoMoreInteractionsFailsWhenOnLyOneMethodLeft
✅ thatVerifyNoMoreInteractionsPass
✅ thatVerifyThrowsExceptionWhenCallsIsInvochedFromStandardMock
✅ thatVerifyTimes
✅ thatVerifyTimesPassWhenAnotherMethodIsCalledBetweenMethodsCalls
✅ thatVerifyTimesPassWhenAnotherMethodIsCalledBetweenMethodsCalls2
✅ thatVerifyTimesPassWhenAnotherMethodIsCalledBetweenMethodsCalls3
✅ thatVerifyTimesPassWhenAnotherMethodIsCalledBetweenMethodsCalls4
✅ thatVerifyTimesThrowsExceptionIfCalledLessTimesThanExpected
✅ thatVerifyTimesThrowsExceptionIfCalledMoreTimesThanExpected
✅ thatVerifyTimesThrowsExceptionWhenAnotherMethodIsCalledBetweenMethodsCalls
✅ thatWithOldNotation
✅ thatWithOldNotationPassWhenAnotherMethodIsCalledBetweenMethodsCalls
✅ thatWithOldNotationThrowsExceptionIfCalledLessTimesThanExpected
✅ thatWithOldNotationThrowsExceptionIfCalledMoreTimesThanExpected
✅ thatWithOldNotationThrowsExceptionWhenAnotherMethodIsCalledBetweenMethodsCalls
✅ verifyAtLeastAndCapture
✅ verifyCallsAndCapture
✅ verifyTimesAndCaptor
fflib_IDGeneratorTest
✅ itShouldGenerateValidIDs
```

File diff suppressed because it is too large Load diff

View file

@ -2,9 +2,11 @@
exports[`dart-json tests matches report snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/dart-json.json",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Test 1",
@ -72,6 +74,7 @@ test\\main_test.dart 17:9 main.<fn>.<fn>.<fn>
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -107,9 +110,11 @@ test\\main_test.dart 17:9 main.<fn>.<fn>.<fn>
exports[`dart-json tests report from rrousselGit/provider test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/external/flutter/provider-test-results.json",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "valueListenableProvider",
@ -178,6 +183,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "ListenableProvider",
@ -295,6 +301,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "consumer",
@ -439,6 +446,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -515,6 +523,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "ChangeNotifierProvider",
@ -690,6 +699,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "MultiProvider",
@ -719,6 +729,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -783,6 +794,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -985,6 +997,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -1014,6 +1027,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -1090,6 +1104,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -1177,6 +1192,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -1699,6 +1715,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "ListenableProxyProvider",
@ -1787,6 +1804,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -1900,6 +1918,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "",
@ -1935,6 +1954,7 @@ Unexpected number of calls
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "ProxyProvider",

View file

@ -2,9 +2,11 @@
exports[`dotnet-nunit tests report from ./reports/dotnet test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/dotnet-nunit.xml",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "CalculatorTests",

View file

@ -2,9 +2,11 @@
exports[`dotnet-trx tests matches report snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/dotnet-trx.trx",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -131,9 +133,11 @@ Actual: False",
exports[`dotnet-trx tests report from FluentValidation test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/external/FluentValidation.Tests.trx",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -355,6 +359,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -396,6 +401,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -419,6 +425,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -658,6 +665,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -747,6 +755,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -776,6 +785,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -799,6 +809,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -906,6 +917,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1019,6 +1031,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1138,6 +1151,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1161,6 +1175,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1190,6 +1205,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1237,6 +1253,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1308,6 +1325,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1499,6 +1517,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1726,6 +1745,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1791,6 +1811,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1874,6 +1895,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1945,6 +1967,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -1992,6 +2015,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2117,6 +2141,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2152,6 +2177,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2367,6 +2393,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2462,6 +2489,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2551,6 +2579,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2670,6 +2699,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2747,6 +2777,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2764,6 +2795,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -2901,6 +2933,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3008,6 +3041,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3097,6 +3131,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3204,6 +3239,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3251,6 +3287,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3274,6 +3311,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3339,6 +3377,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3410,6 +3449,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3433,6 +3473,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3462,6 +3503,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3533,6 +3575,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3610,6 +3653,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3651,6 +3695,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3692,6 +3737,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3763,6 +3809,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3804,6 +3851,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3857,6 +3905,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -3958,6 +4007,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4143,6 +4193,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4238,6 +4289,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4375,6 +4427,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4422,6 +4475,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4685,6 +4739,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4702,6 +4757,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4773,6 +4829,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4802,6 +4859,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4837,6 +4895,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4890,6 +4949,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -4925,6 +4985,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5020,6 +5081,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5079,6 +5141,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5120,6 +5183,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5191,6 +5255,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5646,9 +5711,11 @@ TestRunResult {
exports[`dotnet-trx tests report from SilentNotes test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/external/SilentNotes.trx",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5696,6 +5763,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5737,6 +5805,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5790,6 +5859,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5813,6 +5883,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5848,6 +5919,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5883,6 +5955,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5924,6 +5997,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -5989,6 +6063,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -6018,6 +6093,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -6083,6 +6159,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -6124,6 +6201,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -6177,6 +6255,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,9 +2,11 @@
exports[`mocha-json tests report from ./reports/mocha-json test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/mocha-json.json",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Test 1",
@ -78,6 +80,7 @@ false !== true
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": null,
@ -114,9 +117,11 @@ false !== true
exports[`mocha-json tests report from mochajs/mocha test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/external/mocha/mocha-test-results.json",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "class BufferedWorkerPool constructor",
@ -267,6 +272,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "cli/config findConfig()",
@ -378,6 +384,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "node-flags impliesNoTimeouts()",
@ -1044,6 +1051,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "options loadOptions() "extension" handling when user does not supply "extension" option",
@ -1366,6 +1374,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "helpers list() when given a comma-delimited string",
@ -1461,6 +1470,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "command run builder array type",
@ -1727,6 +1737,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Mocha instance method addFile()",
@ -1962,6 +1973,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "parallel-buffered-runner ParallelBufferedRunner constructor",
@ -2162,6 +2174,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "ParallelBuffered constructor",
@ -2224,6 +2237,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "serializer function deserialize when passed a non-object value",
@ -2635,6 +2649,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "stackTraceFilter() on browser",
@ -2692,6 +2707,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "utils function canonicalType()",
@ -2743,6 +2759,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "worker when run as main process",
@ -2894,6 +2911,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Context nested",
@ -2978,6 +2996,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "durations when fast",
@ -3017,6 +3036,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Errors createForbiddenExclusivityError() when Mocha instance is not running in a worker process",
@ -3146,6 +3166,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "global leaks",
@ -3181,6 +3202,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Mocha .grep()",
@ -3255,6 +3277,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "async hooks",
@ -3284,6 +3307,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "serial nested",
@ -3324,6 +3348,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "serial hooks",
@ -3353,6 +3378,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "hook timeout",
@ -3370,6 +3396,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Hook error",
@ -3410,6 +3437,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Mocha constructor",
@ -4517,6 +4545,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "overspecified asynchronous resolution method",
@ -4534,6 +4563,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "parseQuery()",
@ -4557,6 +4587,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "plugin module class PluginLoader constructor when passed custom plugins",
@ -4985,6 +5016,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "using imported describe",
@ -5002,6 +5034,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "root",
@ -5019,6 +5052,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Runnable(title, fn) .run(fn) if async",
@ -5570,6 +5604,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Runner instance method _uncaught() when called with a non-Runner context",
@ -6218,6 +6253,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Suite instance method addSuite()",
@ -6731,6 +6767,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "Test .clone()",
@ -6847,6 +6884,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "a test that throws non-extensible",
@ -6922,6 +6960,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "timeouts",
@ -7011,6 +7050,7 @@ TestRunResult {
"totalTime": undefined,
},
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "lib/utils canonicalType()",

View file

@ -2,9 +2,11 @@
exports[`rspec-json tests report from ./reports/rspec-json test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/rspec-json.json",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "CheckEnvVars#call when all env vars are defined behaves like success load",

View file

@ -2,9 +2,11 @@
exports[`swift-xunit tests report from swift test results matches snapshot 1`] = `
TestRunResult {
"coveragePercentage": undefined,
"path": "fixtures/swift-xunit.xml",
"suites": [
TestSuiteResult {
"coveragePercentage": undefined,
"groups": [
TestGroupResult {
"name": "AcmeLibTests.AcmeLibTests",

View file

@ -0,0 +1,45 @@
import path from 'node:path';
import fs from 'node:fs';
import { ParseOptions } from '../src/test-parser';
import { normalizeFilePath } from '../src/utils/path-utils';
import { ApexJsonParser } from '../src/parsers/apex-json/apex-json-parsers';
import { getReport } from '../src/report/get-report';
describe('apex-json tests', () => {
it('produces empty test run result when there are no test cases', async () => {
const fixturePath = path.join(__dirname, 'fixtures', 'empty', 'apex-json.json')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const parser = new ApexJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result.tests).toBe(0)
expect(result.result).toBe('success')
});
it('matches report snapshot', async () => {
const opts: ParseOptions = {
parseErrors: true,
trackedFiles: []
}
const fixturePath = path.join(__dirname, 'fixtures', 'apex-json.json')
const outputPath = path.join(__dirname, '__outputs__', 'apex-json.md')
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
const parser = new ApexJsonParser(opts)
const result = await parser.parse(filePath, fileContent)
expect(result).toMatchSnapshot()
const report = getReport([result])
fs.mkdirSync(path.dirname(outputPath), {recursive: true})
fs.writeFileSync(outputPath, report)
})
});

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
{
"result": {
"summary": {
"failRate": "0%",
"failing": 0,
"hostname": "https://scratch.my.salesforce.com",
"orgId": "0000000000000",
"outcome": "Passed",
"passRate": "0%",
"passing": 0,
"skipped": 0,
"testRunId": "000000000000",
"testStartTime": "2024-07-11T15:21:00.000Z",
"testsRan": 0,
"userId": "000000000000000",
"username": "test@example.com",
"commandTime": "357 ms",
"testExecutionTime": "1000 ms",
"testTotalTime": "1000 ms",
"orgWideCoverage": "0%",
"testRunCoverage": "0%"
},
"tests": []
}
}

View file

@ -1,6 +1,6 @@
name: Test Reporter
description: |
Shows test results in GitHub UI: .NET (xUnit, NUnit, MSTest), Dart, Flutter, Java (JUnit), JavaScript (JEST, Mocha)
Shows test results in GitHub UI: .NET (xUnit, NUnit, MSTest), Dart, Flutter, Java (JUnit), JavaScript (JEST, Mocha), Apex (Salesforce via json)
author: Michal Dorner <dorner.michal@gmail.com>
inputs:
artifact:
@ -34,6 +34,7 @@ inputs:
- mocha-json
- rspec-json
- swift-xunit
- apex-json
required: true
list-suites:
description: |
@ -89,6 +90,12 @@ inputs:
description: GitHub Access Token
required: false
default: ${{ github.token }}
create-pr-comment:
description: |
Allows you to create a comment on the pull request with the test results.
If enabled, the comment will contain a summary of the test results
default: 'false'
required: false
outputs:
conclusion:
description: |

117
dist/index.js generated vendored
View file

@ -250,6 +250,7 @@ const rspec_json_parser_1 = __nccwpck_require__(406);
const swift_xunit_parser_1 = __nccwpck_require__(5366);
const path_utils_1 = __nccwpck_require__(4070);
const github_utils_1 = __nccwpck_require__(3522);
const apex_json_parsers_1 = __nccwpck_require__(3754);
async function main() {
try {
const testReporter = new TestReporter();
@ -278,6 +279,7 @@ class TestReporter {
useActionsSummary = core.getInput('use-actions-summary', { required: false }) === 'true';
badgeTitle = core.getInput('badge-title', { required: false });
token = core.getInput('token', { required: true });
createPRComment = core.getInput('create-pr-comment', { required: false }) === 'true';
octokit;
context = (0, github_utils_1.getCheckRunContext)();
constructor() {
@ -417,6 +419,18 @@ class TestReporter {
core.info(`Check run HTML: ${resp.data.html_url}`);
core.setOutput('url', resp.data.url);
core.setOutput('url_html', resp.data.html_url);
if (this.createPRComment) {
const { pull_request } = github.context.payload;
if (pull_request) {
core.info('Attaching Test Summary as a comment to the PR');
const comment = `## Test Summary\n\n${summary}`;
await this.octokit.rest.issues.createComment({
...github.context.repo,
issue_number: pull_request.number,
body: comment
});
}
}
}
return results;
}
@ -440,6 +454,8 @@ class TestReporter {
return new rspec_json_parser_1.RspecJsonParser(options);
case 'swift-xunit':
return new swift_xunit_parser_1.SwiftXunitParser(options);
case 'apex-json':
return new apex_json_parsers_1.ApexJsonParser(options);
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`);
}
@ -448,6 +464,67 @@ class TestReporter {
main();
/***/ }),
/***/ 3754:
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ApexJsonParser = void 0;
const test_results_1 = __nccwpck_require__(2768);
class ApexJsonParser {
options;
constructor(options) {
this.options = options;
}
async parse(path, content) {
const report = await this.getReport(path, content);
return this.getTestRunResult(path, report);
}
async getReport(path, content) {
try {
return JSON.parse(content);
}
catch (e) {
throw new Error(`Invalid JSON at ${path}\n\n${e}`);
}
}
getTestRunResult(path, report) {
const time = report.result.summary.testTotalTime;
const timeAsNumber = Number.parseInt(time, 10);
// group tests by test.ApexClass.Name
const groupsMap = report.result.tests.reduce((map, test) => {
const key = test.ApexClass.Name;
const testResults = map.get(key) || [];
let result = 'skipped';
if (test.Outcome === 'Pass') {
result = 'success';
}
else if (test.Outcome === 'Fail') {
result = 'failed';
}
const testCaseError = test.Message ? { details: test.Message } : undefined;
const testResult = new test_results_1.TestCaseResult(test.MethodName, result, test.RunTime, testCaseError);
testResults.push(testResult);
map.set(key, testResults);
return map;
}, new Map());
const groups = [];
for (const [name, tests] of groupsMap) {
const suite = new test_results_1.TestGroupResult(name, tests);
groups.push(suite);
}
const coverageString = report.result.summary.testRunCoverage;
const coverage = coverageString ? Number.parseInt(coverageString.replace('%', ''), 10) : undefined;
const suite = new test_results_1.TestSuiteResult('Apex Tests', groups, timeAsNumber, coverage);
return new test_results_1.TestRunResult(path, [suite], timeAsNumber, coverage);
}
}
exports.ApexJsonParser = ApexJsonParser;
/***/ }),
/***/ 4528:
@ -1854,6 +1931,13 @@ function getTestRunsReport(testRuns, options) {
sections.push(`<details><summary>Expand for details</summary>`);
sections.push(` `);
}
const shouldShowCoverage = testRuns.some(tr => tr.coverage !== undefined);
const columnNames = ['Report', 'Passed', 'Failed', 'Skipped', 'Time'];
const columnAligns = [markdown_utils_1.Align.Left, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right];
if (shouldShowCoverage) {
columnNames.push('Coverage');
columnAligns.push(markdown_utils_1.Align.Right);
}
if (testRuns.length > 0 || options.onlySummary) {
const tableData = testRuns
.filter(tr => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
@ -1863,9 +1947,13 @@ function getTestRunsReport(testRuns, options) {
const passed = tr.passed > 0 ? `${tr.passed} ${markdown_utils_1.Icon.success}` : '';
const failed = tr.failed > 0 ? `${tr.failed} ${markdown_utils_1.Icon.fail}` : '';
const skipped = tr.skipped > 0 ? `${tr.skipped} ${markdown_utils_1.Icon.skip}` : '';
if (shouldShowCoverage) {
const coverage = tr.coverage !== undefined ? tr.coverage + '%' : '';
return [name, passed, failed, skipped, time, coverage];
}
return [name, passed, failed, skipped, time];
});
const resultsTable = (0, markdown_utils_1.table)(['Report', 'Passed', 'Failed', 'Skipped', 'Time'], [markdown_utils_1.Align.Left, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right], ...tableData);
const resultsTable = (0, markdown_utils_1.table)(columnNames, columnAligns, ...tableData);
sections.push(resultsTable);
}
if (options.onlySummary === false) {
@ -1891,7 +1979,14 @@ function getSuitesReport(tr, runIndex, options) {
: 'No tests found';
sections.push(headingLine2);
if (suites.length > 0) {
const suitesTable = (0, markdown_utils_1.table)(['Test suite', 'Passed', 'Failed', 'Skipped', 'Time'], [markdown_utils_1.Align.Left, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right], ...suites.map((s, suiteIndex) => {
const shouldShowCoverage = suites.some(s => s.coverage !== undefined);
const columnNames = ['Test suite', 'Passed', 'Failed', 'Skipped', 'Time'];
const columnAligns = [markdown_utils_1.Align.Left, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right];
if (shouldShowCoverage) {
columnNames.push('Coverage');
columnAligns.push(markdown_utils_1.Align.Right);
}
const suitesTable = (0, markdown_utils_1.table)(columnNames, columnAligns, ...suites.map((s, suiteIndex) => {
const tsTime = (0, markdown_utils_1.formatTime)(s.time);
const tsName = s.name;
const skipLink = options.listTests === 'none' || (options.listTests === 'failed' && s.result !== 'failed');
@ -1900,6 +1995,10 @@ function getSuitesReport(tr, runIndex, options) {
const passed = s.passed > 0 ? `${s.passed} ${markdown_utils_1.Icon.success}` : '';
const failed = s.failed > 0 ? `${s.failed} ${markdown_utils_1.Icon.fail}` : '';
const skipped = s.skipped > 0 ? `${s.skipped} ${markdown_utils_1.Icon.skip}` : '';
const coverage = s.coverage !== undefined ? s.coverage + '%' : '';
if (shouldShowCoverage) {
return [tsNameLink, passed, failed, skipped, tsTime, coverage];
}
return [tsNameLink, passed, failed, skipped, tsTime];
}));
sections.push(suitesTable);
@ -1985,10 +2084,12 @@ class TestRunResult {
path;
suites;
totalTime;
constructor(path, suites, totalTime) {
coveragePercentage;
constructor(path, suites, totalTime, coveragePercentage) {
this.path = path;
this.suites = suites;
this.totalTime = totalTime;
this.coveragePercentage = coveragePercentage;
}
get tests() {
return this.suites.reduce((sum, g) => sum + g.tests, 0);
@ -2005,6 +2106,9 @@ class TestRunResult {
get time() {
return this.totalTime ?? this.suites.reduce((sum, g) => sum + g.time, 0);
}
get coverage() {
return this.coveragePercentage;
}
get result() {
return this.suites.some(t => t.result === 'failed') ? 'failed' : 'success';
}
@ -2025,10 +2129,12 @@ class TestSuiteResult {
name;
groups;
totalTime;
constructor(name, groups, totalTime) {
coveragePercentage;
constructor(name, groups, totalTime, coveragePercentage) {
this.name = name;
this.groups = groups;
this.totalTime = totalTime;
this.coveragePercentage = coveragePercentage;
}
get tests() {
return this.groups.reduce((sum, g) => sum + g.tests.length, 0);
@ -2045,6 +2151,9 @@ class TestSuiteResult {
get time() {
return this.totalTime ?? this.groups.reduce((sum, g) => sum + g.time, 0);
}
get coverage() {
return this.coveragePercentage;
}
get result() {
return this.groups.some(t => t.result === 'failed') ? 'failed' : 'success';
}

8
package-lock.json generated
View file

@ -22,7 +22,7 @@
"@octokit/webhooks-types": "^7.5.1",
"@types/adm-zip": "^0.5.5",
"@types/jest": "^29.5.12",
"@types/node": "^20.14.8",
"@types/node": "^20.14.10",
"@types/picomatch": "^2.3.3",
"@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^7.14.1",
@ -1647,9 +1647,9 @@
}
},
"node_modules/@types/node": {
"version": "20.14.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz",
"integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==",
"version": "20.14.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz",
"integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==",
"dependencies": {
"undici-types": "~5.26.4"
}

View file

@ -46,7 +46,7 @@
"@octokit/webhooks-types": "^7.5.1",
"@types/adm-zip": "^0.5.5",
"@types/jest": "^29.5.12",
"@types/node": "^20.14.8",
"@types/node": "^20.14.10",
"@types/picomatch": "^2.3.3",
"@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^7.14.1",

View file

@ -21,6 +21,7 @@ import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
import {getCheckRunContext} from './utils/github-utils'
import {ApexJsonParser} from './parsers/apex-json/apex-json-parsers'
async function main(): Promise<void> {
try {
@ -48,6 +49,7 @@ class TestReporter {
readonly useActionsSummary = core.getInput('use-actions-summary', {required: false}) === 'true'
readonly badgeTitle = core.getInput('badge-title', {required: false})
readonly token = core.getInput('token', {required: true})
readonly createPRComment = core.getInput('create-pr-comment', {required: false}) === 'true'
readonly octokit: InstanceType<typeof GitHub>
readonly context = getCheckRunContext()
@ -218,6 +220,22 @@ class TestReporter {
core.info(`Check run HTML: ${resp.data.html_url}`)
core.setOutput('url', resp.data.url)
core.setOutput('url_html', resp.data.html_url)
if (this.createPRComment) {
const {pull_request} = github.context.payload
if (pull_request) {
core.info('Attaching Test Summary as a comment to the PR')
const comment = `## Test Summary\n\n${summary}`
await this.octokit.rest.issues.createComment({
...github.context.repo,
issue_number: pull_request.number,
body: comment
})
}
}
}
return results
@ -243,6 +261,8 @@ class TestReporter {
return new RspecJsonParser(options)
case 'swift-xunit':
return new SwiftXunitParser(options)
case 'apex-json':
return new ApexJsonParser(options)
default:
throw new Error(`Input variable 'reporter' is set to invalid value '${reporter}'`)
}

View file

@ -0,0 +1,68 @@
import {ParseOptions, TestParser} from '../../test-parser'
import {
TestCaseError,
TestCaseResult,
TestExecutionResult,
TestGroupResult,
TestRunResult,
TestSuiteResult
} from '../../test-results'
import {ApexTestReport} from './apex-json-types'
export class ApexJsonParser implements TestParser {
constructor(readonly options: ParseOptions) {}
async parse(path: string, content: string): Promise<TestRunResult> {
const report = await this.getReport(path, content)
return this.getTestRunResult(path, report)
}
private async getReport(path: string, content: string): Promise<ApexTestReport> {
try {
return JSON.parse(content) as ApexTestReport
} catch (e) {
throw new Error(`Invalid JSON at ${path}\n\n${e}`)
}
}
private getTestRunResult(path: string, report: ApexTestReport): TestRunResult {
const time = report.result.summary.testTotalTime
const timeAsNumber = Number.parseInt(time, 10)
// group tests by test.ApexClass.Name
const groupsMap: Map<string, TestCaseResult[]> = report.result.tests.reduce((map, test) => {
const key = test.ApexClass.Name
const testResults = map.get(key) || []
let result: TestExecutionResult = 'skipped'
if (test.Outcome === 'Pass') {
result = 'success'
} else if (test.Outcome === 'Fail') {
result = 'failed'
}
const testCaseError: TestCaseError | undefined = test.Message ? {details: test.Message} : undefined
const testResult = new TestCaseResult(test.MethodName, result, test.RunTime, testCaseError)
testResults.push(testResult)
map.set(key, testResults)
return map
}, new Map<string, TestCaseResult[]>())
const groups: TestGroupResult[] = []
for (const [name, tests] of groupsMap) {
const suite = new TestGroupResult(name, tests)
groups.push(suite)
}
const coverageString = report.result.summary.testRunCoverage
const coverage = coverageString ? Number.parseInt(coverageString.replace('%', ''), 10) : undefined
const suite = new TestSuiteResult('Apex Tests', groups, timeAsNumber, coverage)
return new TestRunResult(path, [suite], timeAsNumber, coverage)
}
}

View file

@ -0,0 +1,92 @@
export interface ApexTestReport {
result: Result
}
export interface Result {
summary: SuiteSummary
tests: Test[]
coverage: SuiteCoverage
}
export interface SuiteCoverage {
coverage?: Coverage[]
records: ApexRecord[]
summary: SuiteCoverageSummary
}
export interface SuiteCoverageSummary {
totalLines: number
coveredLines: number
orgWideCoverage: string
testRunCoverage: string
}
export interface ApexRecord {
ApexTestClass: ApexTestClass
Coverage: RecordCoverage
TestMethodName: string
NumLinesCovered: number
ApexClassOrTrigger: ApexTestClass
NumLinesUncovered: number
}
export interface RecordCoverage {
coveredLines: number[]
uncoveredLines: number[]
}
export interface ApexTestClass {
Id: string
Name: string
}
export interface Coverage {
id: string
name: string
totalLines: number
lines: Lines
totalCovered: number
coveredPercent: number
}
export type Lines = Record<number, number>
export interface Test {
Id: string
QueueItemId: string
StackTrace: null
Message: string | null
AsyncApexJobId: string
MethodName: string
Outcome: string
ApexClass: ApexClass
RunTime: number
FullName: string
}
export interface ApexClass {
Id: string
Name: string
NamespacePrefix: string
}
export interface SuiteSummary {
failRate: string
failing: number
hostname: string
orgId: string
outcome: string
passRate: string
passing: number
skipped: number
testRunId: string
testStartTime: string
testsRan: number
userId: string
username: string
commandTime: string
testExecutionTime: string
testTotalTime: string
orgWideCoverage: string
testRunCoverage: string
}

View file

@ -149,6 +149,16 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
sections.push(` `)
}
const shouldShowCoverage = testRuns.some(tr => tr.coverage !== undefined)
const columnNames = ['Report', 'Passed', 'Failed', 'Skipped', 'Time']
const columnAligns = [Align.Left, Align.Right, Align.Right, Align.Right, Align.Right]
if (shouldShowCoverage) {
columnNames.push('Coverage')
columnAligns.push(Align.Right)
}
if (testRuns.length > 0 || options.onlySummary) {
const tableData = testRuns
.filter(tr => tr.passed > 0 || tr.failed > 0 || tr.skipped > 0)
@ -158,14 +168,16 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
const passed = tr.passed > 0 ? `${tr.passed} ${Icon.success}` : ''
const failed = tr.failed > 0 ? `${tr.failed} ${Icon.fail}` : ''
const skipped = tr.skipped > 0 ? `${tr.skipped} ${Icon.skip}` : ''
if (shouldShowCoverage) {
const coverage = tr.coverage !== undefined ? tr.coverage + '%' : ''
return [name, passed, failed, skipped, time, coverage]
}
return [name, passed, failed, skipped, time]
})
const resultsTable = table(
['Report', 'Passed', 'Failed', 'Skipped', 'Time'],
[Align.Left, Align.Right, Align.Right, Align.Right, Align.Right],
...tableData
)
const resultsTable = table(columnNames, columnAligns, ...tableData)
sections.push(resultsTable)
}
@ -198,9 +210,19 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
sections.push(headingLine2)
if (suites.length > 0) {
const shouldShowCoverage = suites.some(s => s.coverage !== undefined)
const columnNames = ['Test suite', 'Passed', 'Failed', 'Skipped', 'Time']
const columnAligns = [Align.Left, Align.Right, Align.Right, Align.Right, Align.Right]
if (shouldShowCoverage) {
columnNames.push('Coverage')
columnAligns.push(Align.Right)
}
const suitesTable = table(
['Test suite', 'Passed', 'Failed', 'Skipped', 'Time'],
[Align.Left, Align.Right, Align.Right, Align.Right, Align.Right],
columnNames,
columnAligns,
...suites.map((s, suiteIndex) => {
const tsTime = formatTime(s.time)
const tsName = s.name
@ -210,6 +232,13 @@ function getSuitesReport(tr: TestRunResult, runIndex: number, options: ReportOpt
const passed = s.passed > 0 ? `${s.passed} ${Icon.success}` : ''
const failed = s.failed > 0 ? `${s.failed} ${Icon.fail}` : ''
const skipped = s.skipped > 0 ? `${s.skipped} ${Icon.skip}` : ''
const coverage = s.coverage !== undefined ? s.coverage + '%' : ''
if (shouldShowCoverage) {
return [tsNameLink, passed, failed, skipped, tsTime, coverage]
}
return [tsNameLink, passed, failed, skipped, tsTime]
})
)

View file

@ -4,7 +4,8 @@ export class TestRunResult {
constructor(
readonly path: string,
readonly suites: TestSuiteResult[],
private totalTime?: number
private totalTime?: number,
private coveragePercentage?: number
) {}
get tests(): number {
@ -25,6 +26,10 @@ export class TestRunResult {
return this.totalTime ?? this.suites.reduce((sum, g) => sum + g.time, 0)
}
get coverage(): number | undefined {
return this.coveragePercentage
}
get result(): TestExecutionResult {
return this.suites.some(t => t.result === 'failed') ? 'failed' : 'success'
}
@ -47,7 +52,8 @@ export class TestSuiteResult {
constructor(
readonly name: string,
readonly groups: TestGroupResult[],
private totalTime?: number
private totalTime?: number,
private coveragePercentage?: number
) {}
get tests(): number {
@ -66,6 +72,9 @@ export class TestSuiteResult {
get time(): number {
return this.totalTime ?? this.groups.reduce((sum, g) => sum + g.time, 0)
}
get coverage(): number | undefined {
return this.coveragePercentage
}
get result(): TestExecutionResult {
return this.groups.some(t => t.result === 'failed') ? 'failed' : 'success'