/**
*
* Copyright
* 2009-2015 Jayway Products AB
* 2016-2017 Föreningen Sambruk
*
* Licensed under AGPL, Version 3.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/agpl.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package se.streamsource.streamflow.web.context.cases;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.qi4j.api.util.Iterables.first;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.commons.collections.ArrayStack;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.unitofwork.UnitOfWork;
import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
import org.qi4j.api.usecase.UsecaseBuilder;
import org.qi4j.api.util.Function;
import org.qi4j.api.util.Iterables;
import se.streamsource.dci.api.Contexts;
import se.streamsource.dci.api.InteractionConstraints;
import se.streamsource.dci.api.RoleMap;
import se.streamsource.dci.value.link.LinkValue;
import se.streamsource.dci.value.table.TableQuery;
import se.streamsource.streamflow.web.application.security.UserPrincipal;
import se.streamsource.streamflow.web.context.ContextTest;
import se.streamsource.streamflow.web.context.administration.CaseTypesContext;
import se.streamsource.streamflow.web.context.administration.MembersContext;
import se.streamsource.streamflow.web.context.administration.OrganizationalUnitsContext;
import se.streamsource.streamflow.web.context.administration.OrganizationsContext;
import se.streamsource.streamflow.web.context.administration.ProjectsContext;
import se.streamsource.streamflow.web.context.administration.ResolutionsContext;
import se.streamsource.streamflow.web.context.administration.SelectedCaseTypesContext;
import se.streamsource.streamflow.web.context.administration.SelectedResolutionsContext;
import se.streamsource.streamflow.web.context.administration.labels.LabelsContext;
import se.streamsource.streamflow.web.context.administration.labels.SelectedLabelsContext;
import se.streamsource.streamflow.web.context.organizations.OrganizationalUnitsContextTest;
import se.streamsource.streamflow.web.context.organizations.ProjectsContextTest;
import se.streamsource.streamflow.web.context.users.UsersContextTest;
import se.streamsource.streamflow.web.context.workspace.CaseSearchResult;
import se.streamsource.streamflow.web.context.workspace.DraftsContext;
import se.streamsource.streamflow.web.context.workspace.WorkspaceProjectsContext;
import se.streamsource.streamflow.web.context.workspace.cases.CaseCommandsContext;
import se.streamsource.streamflow.web.context.workspace.cases.general.CaseGeneralCommandsContext;
import se.streamsource.streamflow.web.context.workspace.cases.general.LabelableContext;
import se.streamsource.streamflow.web.domain.entity.organization.GlobalCaseIdStateEntity;
import se.streamsource.streamflow.web.domain.entity.organization.OrganizationsEntity;
import se.streamsource.streamflow.web.domain.interaction.gtd.CaseId;
import se.streamsource.streamflow.web.domain.structure.caze.Case;
import se.streamsource.streamflow.web.domain.structure.label.Label;
import se.streamsource.streamflow.web.domain.structure.organization.Organization;
import se.streamsource.streamflow.web.domain.structure.organization.Organizations;
import se.streamsource.streamflow.web.domain.structure.project.Project;
import se.streamsource.streamflow.web.domain.structure.user.User;
/**
* Check lifecycle of a case
*/
public class CaseCommandsContextTest
extends ContextTest
{
InteractionConstraints constraints;
@BeforeClass
public static void before() throws UnitOfWorkCompletionException
{
{
OrganizationalUnitsContextTest.createOU( "OU1" );
}
{
ProjectsContextTest.createProject( "OU1", "Project1" );
ProjectsContextTest.createProject( "OU1", "Project2" );
}
Project project1;
Organization org;
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "1" ));
RoleMap.newCurrentRoleMap();
playRole( Organizations.class, OrganizationsEntity.ORGANIZATIONS_ID );
org = playRole( Organization.class, findLink( context( OrganizationsContext.class ).index(), "Organization" ) );
playRole( findDescribable( context( OrganizationalUnitsContext.class ).index(), "OU1" ) );
project1 = findDescribable( context( ProjectsContext.class ).index(), "Project1" );
playRole( project1 );
CaseTypesContext caseTypes = context( CaseTypesContext.class );
caseTypes.create( "CaseType1" );
SelectedCaseTypesContext selectedCaseTypes = context( SelectedCaseTypesContext.class );
selectedCaseTypes.addcasetype( entityValue( findLink( selectedCaseTypes.possiblecasetypes(), "CaseType1" ) ) );
playRole( findDescribable( caseTypes.index(), "CaseType1" ) );
ResolutionsContext resolutionsContext = context( ResolutionsContext.class );
resolutionsContext.create( "Resolution1" );
SelectedResolutionsContext selectedResolutionsContext = context( SelectedResolutionsContext.class );
selectedResolutionsContext.addresolution( entityValue( findLink( selectedResolutionsContext.possibleresolutions(), "Resolution1" ) ) );
uow.complete();
}
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "2" ));
RoleMap.newCurrentRoleMap();
playRole( org );
playRole( project1 );
context( LabelsContext.class ).create( "Label1" );
SelectedLabelsContext context = context( SelectedLabelsContext.class );
context.addlabel( CaseCommandsContextTest.<Label>entity( findLink( context.possiblelabels(), "Label1" ) ) );
uow.complete();
}
UsersContextTest.createUser( "testing" );
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "3" ));
RoleMap.newCurrentRoleMap();
playRole( project1 );
context( MembersContext.class ).addmember( entityValue( "testing" ) );
uow.complete();
}
clearEvents();
}
@Before
public void services()
{
constraints = serviceLocator.<InteractionConstraints>findService( InteractionConstraints.class ).get();
}
@Test
public void testCaseActions() throws UnitOfWorkCompletionException
{
// Create draft
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "4" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
drafts.createcase();
uow.complete();
eventsOccurred( "createdCase", "addedContact" );
}
// Check that draft exists
Case caze;
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "5" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
CaseSearchResult result = drafts.cases( valueBuilderFactory.newValueFromJSON( TableQuery.class, "{tq:'select *'}" ) );
assertThat( Iterables.count( result.getResult() ), equalTo( 1L ) );
caze = first( result.getResult() );
uow.discard();
}
// Name draft
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "6" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
context( CaseGeneralCommandsContext.class ).changedescription( "Case1" );
uow.complete();
eventsOccurred( "changedDescription" );
}
// Check actions for new draft
{
checkActions( caze, null, "delete", "sendto" );
}
// Send to project
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "7" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
CaseCommandsContext context = context( CaseCommandsContext.class );
LinkValue project1 = findLink(context.possiblesendto(), "Project1");
context.sendto( entityValue( project1 ) );
uow.complete();
eventsOccurred( "changedOwner", "changedDate", "setCounter", "assignedCaseId" );
}
// Check actions for draft sent to project
{
checkActions( caze, "Project1", "delete", "open", "sendto" );
}
// Select casetype
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "8" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
CaseGeneralCommandsContext context = context( CaseGeneralCommandsContext.class );
context.casetype( entityValue( findLink( context.possiblecasetypes(), "CaseType1" ) ) );
uow.complete();
eventsOccurred( "changedCaseType" );
}
// Add label
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "9" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
LabelableContext context = context( LabelableContext.class );
context.addlabel( entityValue( findLink( context.possiblelabels(), "Label1" ) ) );
uow.complete();
eventsOccurred( "addedLabel" );
}
// Open case
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "10" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
context( CaseCommandsContext.class ).open();
uow.complete();
eventsOccurred( "changedStatus" );
}
// Check open actions
{
checkActions( caze, "Project1", "delete", "resolve", "read", "markread", "sendto", "restrict", "assign", "assignto" );
}
// Assign case
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "11" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( Project.class, findLink( context( WorkspaceProjectsContext.class ).index(), "Project1" ) );
// TODO This is random! playRole( first( context( InboxContext.class ).index() ) );
playRole( caze );
context( CaseCommandsContext.class ).assign();
uow.complete();
eventsOccurred( "assignedTo" );
}
// Check assigned actions
{
checkActions( caze, "Project1", "delete", "resolve", "markread", "read", "sendto", "restrict", "unassign" );
}
// Resolve case
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "12" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( Project.class, findLink( context( WorkspaceProjectsContext.class ).index(), "Project1" ) );
// playRole( first( context( AssignmentsContext.class ).index() ) );
playRole( caze );
// uow.metaInfo().set( new UserPrincipal("test") );
CaseCommandsContext context = context( CaseCommandsContext.class );
context.resolve( entityValue( findLink( context.possibleresolutions(), "Resolution1" ).id().get() ) );
uow.complete();
eventsOccurred( "resolved", "changedStatus" );
}
// Check resolved actions
{
checkActions( caze, "Project1", "reopen" );
}
// Reopen case
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "13" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
context( CaseCommandsContext.class ).reopen();
uow.complete();
eventsOccurred( "changedStatus", "unresolved" );
}
// Check reopened actions
{
checkActions( caze, "Project1", "delete", "resolve", "markread", "read", "sendto", "restrict", "unassign" );
}
// Close
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "14" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
context( CaseCommandsContext.class ).close();
uow.complete();
eventsOccurred( "changedStatus" );
}
// Check closed actions
{
checkActions( caze, "Project1", "reopen" );
}
// Reopen case and change to project with requires case type
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "15" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
context( CaseCommandsContext.class ).reopen();
uow.complete();
eventsOccurred( "changedStatus", "unresolved" );
}
// Check reopened actions
{
checkActions( caze, "Project1", "delete", "resolve", "markread", "read", "sendto", "restrict", "unassign" );
}
//SentTo
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "16" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
Project project1 = CaseCommandsContextTest.<Project>entity(findLink( context(WorkspaceProjectsContext.class).index(), "Project1" ) );
project1.changeCaseTypeRequired(true);
CaseGeneralCommandsContext generalContext = context( CaseGeneralCommandsContext.class );
generalContext.casetype( entityValueNull() );
uow.complete();
eventsOccurred("changedRequiresCaseType","changedCaseType");
}
{
checkActions( caze, "Project1", "delete", "requirecasetype", "markread", "read", "sendto", "restrict", "unassign" );
}
// Close again with casetype present
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "17" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
CaseGeneralCommandsContext generalContext = context( CaseGeneralCommandsContext.class );
generalContext.casetype( entityValue( findLink( generalContext.possiblecasetypes(), "CaseType1" ) ) );
context( CaseCommandsContext.class ).close();
uow.complete();
eventsOccurred( "changedStatus", "changedCaseType" );
}
// Check closed actions
{
checkActions( caze, "Project1", "reopen" );
}
}
@Test
public void testConcurrentSendToProject() throws UnitOfWorkCompletionException
{
long currentId = 0;
// Create draft1
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "21" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
drafts.createcase();
GlobalCaseIdStateEntity globalCaseId = uow.get(GlobalCaseIdStateEntity.class, GlobalCaseIdStateEntity.GLOBALCASEIDSTATE_ID);
currentId = globalCaseId.getCounter();
uow.complete();
eventsOccurred( "createdCase", "addedContact" );
}
// Check that draft exists
Case caze1;
UnitOfWork uowCaze1 = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "22" ));
{
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
CaseSearchResult result = drafts.cases( valueBuilderFactory.newValueFromJSON( TableQuery.class, "{tq:'select *'}" ) );
//assertThat( Iterables.count( caseList ), equalTo( 1L ) );
caze1 = first( result.getResult() );
}
// Create draft2
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "23" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
drafts.createcase();
uow.complete();
eventsOccurred( "createdCase", "addedContact" );
}
// Check that draft exists
Case caze2;
UnitOfWork uowCaze2 = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "24" ));
{
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
CaseSearchResult result = drafts.cases( valueBuilderFactory.newValueFromJSON( TableQuery.class, "{tq:'select *'}" ) );
//assertThat( Iterables.count( caseList ), equalTo( 2L ) );
caze2 = first( result.getResult() );
}
// Send to project
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "25" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze1 );
CaseCommandsContext context = context( CaseCommandsContext.class );
context.sendto( entityValue( findLink( context.possiblesendto(), "Project1" ) ) );
uow.complete();
eventsOccurred( "changedOwner", "changedDate", "setCounter", "assignedCaseId" );
}
// Send to project2
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "26" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze2 );
CaseCommandsContext context = context( CaseCommandsContext.class );
context.sendto( entityValue( findLink( context.possiblesendto(), "Project2" ) ) );
uow.complete();
eventsOccurred( "changedOwner", "changedDate", "setCounter", "assignedCaseId" );
}
String caseUUID1 = EntityReference.getEntityReference( caze1 ).identity();
String caseUUID2 = EntityReference.getEntityReference( caze2 ).identity();
uowCaze1.discard();
uowCaze2.discard();
SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMdd" );
String date = sdf.format( new Date() );
UnitOfWork readUow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "27" ));
RoleMap.newCurrentRoleMap();
playRole( User.class, "testing" );
RoleMap.current().set( new UserPrincipal( "testing" ) );
DraftsContext drafts = context( DraftsContext.class );
CaseSearchResult result = drafts.cases( valueBuilderFactory.newValueFromJSON( TableQuery.class, "{tq:'select *'}" ) );
long caseCount = currentId + Iterables.count( result.getResult() );
assertTrue( "expected " + date +"-" + (caseCount - 1) , ((CaseId.Data) readUow.get( Case.class, caseUUID1 )).caseId().get().equals( date + "-" + (caseCount - 1) ) );
assertTrue( "expected " + date +"-" + (caseCount), ((CaseId.Data) readUow.get( Case.class, caseUUID2 )).caseId().get().equals( date + "-" + (caseCount) ) );
readUow.discard();
}
private void checkActions( Case caze, String projectId, String... allowedActions )
{
UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "28" ));
RoleMap.newCurrentRoleMap();
RoleMap.current().set( new UserPrincipal( "testing" ) );
playRole( caze );
playRole( User.class, "testing" );
if( projectId != null )
{
playRole( Project.class, findLink( context( WorkspaceProjectsContext.class ).index(), projectId ) );
//playRole( findDescribable( context( ProjectsContext.class ).index(), projectId ) );
}
RoleMap.current().set( new UserPrincipal( "testing" ) );
List<String> actions = new ArrayStack();
Iterables.addAll( actions, Iterables.map( new Function<Method, String>()
{
public String map( Method method )
{
return method.getName();
}
}, Contexts.commands( CaseCommandsContext.class, constraints, RoleMap.current(), moduleInstance ) ) );
assertThat( actions, containsInAnyOrder( allowedActions ));
uow.discard();
}
}