public class RiotUnknownDevicesPageObjects extends TestUtilities {
	private AndroidDriver<MobileElement> driver;
	public RiotUnknownDevicesPageObjects(AppiumDriver<MobileElement> myDriver) throws InterruptedException{
		driver=(AndroidDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(myDriver), this);
		try {
			waitUntilDisplayed((AndroidDriver<MobileElement>) driver,"android:id/parentPanel", true, 5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/*
	 * ALERT TITLE
	 */
	@AndroidFindBy(id="android:id/alertTitle")
	public MobileElement alertTitleTextView;
	
	/*
	 * ALERT BODY
	 */
	@AndroidFindBy(id="im.vector.alpha:id/unknown_devices_list_view")
	public MobileElement alertBodyListView;
	/**
	 * Text view containing the main message.
	 */
	@AndroidFindBy(xpath="//android.widget.ExpandableListView[@resource-id='im.vector.alpha:id/unknown_devices_list_view']//android.widget.TextView")
	public MobileElement alertBodyMessageTextView;
	
	/**
	 * List of the collapsable items containing the unknown devices of a user.
	 */
	@AndroidFindBy(xpath="//android.widget.ExpandableListView[@resource-id='im.vector.alpha:id/unknown_devices_list_view']/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.TextView[@resource-id='im.vector.alpha:id/heading']/../")
	public List<MobileElement> userNameSectionCollapsableList;
	
	/**
	 * List of unknown devices items. An item contains the device name, the device id and the two buttons: verify/unverify, blacklist/unblacklist.
	 */
	@AndroidFindBy(xpath="//android.widget.ExpandableListView[@resource-id='im.vector.alpha:id/unknown_devices_list_view']//android.widget.TextView[@resource-id='im.vector.alpha:id/device_name']/..")
	public List<MobileElement> unknownDevicesItemsList;
	
	/*
	 * ALERT BOTTOM
	 */
	@AndroidFindBy(id="android:id/buttonPanel")
	public MobileElement buttonPanel;
	
	@AndroidFindBy(id="android:id/button1")
	public MobileElement sendAnywayButton;
	@AndroidFindBy(id="android:id/button3")
	public MobileElement okButton;
	
	public void checkUnknownDevicesModal(){
		Assert.assertEquals(alertTitleTextView.getText(), "Room contains unknown devices", "Modal title is wrong.");
		Assert.assertEquals(alertBodyMessageTextView.getText(), "This room contains unknown devices which have not been verified.\nThis means there is no guarantee that the devices belong to the users they claim to.\nWe recommend you go through the verification process for each device before continuing, but you can resend the message without verifying if you prefer.\n\nUnknown devices:", "Modal main message is wrong.");
		Assert.assertTrue(unknownDevicesItemsList.size()>=1, "There is less than 1 device to verify");
		Assert.assertEquals(sendAnywayButton.getText(), "Send Anyway");
		Assert.assertEquals(okButton.getText(), "OK");
	}
	
	/**
	 * Return the device name of an item at indexDevice.
	 * @param indexDevice
	 * @return
	 */
	public String getDeviceNameByIndex(int indexDevice){
		if(indexDevice<unknownDevicesItemsList.size()){
			return unknownDevicesItemsList.get(indexDevice).findElementById("im.vector.alpha:id/device_name").getText();
		}else{
			System.out.println("There is not device item at index "+indexDevice);
			return null;
		}
	}
	
	/**
	 * Return the device id of an item at indexDevice.
	 * @param indexDevice
	 * @return
	 */
	public String getDeviceIDByIndex(int indexDevice){
		if(indexDevice<unknownDevicesItemsList.size()){
			return unknownDevicesItemsList.get(indexDevice).findElementById("im.vector.alpha:id/device_id").getText();
		}else{
			System.out.println("There is not device item at index "+indexDevice);
			return null;
		}
	}
	
	
	/**
	 * Hit the verify button of a device by his index position.
	 * @param indexDevice
	 */
	public MobileElement getVerifyDeviceButton(int indexDevice){
		if(indexDevice<unknownDevicesItemsList.size()){
			return unknownDevicesItemsList.get(indexDevice).findElementById("im.vector.alpha:id/button_verify");
		}else{
			System.out.println("There is not device item at index "+indexDevice);
			return null;
		}
	}
} public class RiotCallingPageObjects extends TestUtilities{
	private IOSDriver<MobileElement> driver;
	public RiotCallingPageObjects(AppiumDriver<MobileElement> myDriver){
		driver= (IOSDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(driver), this);
		try {
			waitUntilDisplayed(driver,"CallVCView", true, 10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	@iOSFindBy(accessibility="CallVCView")
	public MobileElement mainCallLayout;
	
	/*
	 * TOP
	 */
	@iOSFindBy(accessibility="CallVCBackToAppButton")
	public MobileElement menuBackButton;
	@iOSFindBy(accessibility="CallVCCallerNameLabel")
	public MobileElement callerName;
	@iOSFindBy(accessibility="CallVCCallStatusLabel")
	public MobileElement incomingCallStatus;
	@iOSFindBy(accessibility="CallVCCameraSwitchButton")
	public MobileElement switchCameraButton;

	/*
	 * MIDDLE
	 */
	@iOSFindBy(accessibility="CallVCCallerImageView")
	public MobileElement callerImage;
	
	/*
	 * BOTTOM BAR
	 */
	/**
	 * Contains the controls at the bottom of the view.
	 */
	@iOSFindBy(accessibility="CallVCCallControlContainerView")
	public MobileElement callControllContainer;
	@iOSFindBy(accessibility="CallVCAudioMuteButton")
	public MobileElement muteMicButton;
	@iOSFindBy(accessibility="CallVCSpeakerButton")
	public MobileElement muteAudioButton;
	@iOSFindBy(accessibility="CallVCEndCallButton")
	public MobileElement hangUpButton;
	@iOSFindBy(accessibility="CallVCVideoMuteButton")
	public MobileElement muteLocalCameraButton;
	@iOSFindBy(accessibility="CallVCChatButton")
	public MobileElement chatLinkButton;
	
	/**
	 * Asserts true or false if the view is displayed.
	 * @param displayed
	 * @return 
	 * @throws InterruptedException
	 */
	public Boolean isDisplayed(Boolean displayed) throws InterruptedException{
		return waitUntilDisplayed(driver,"CallVCOverlayContainerView", displayed, 10);
	}
	
	/**
	 * Double tap on the hangup button. </br> Usefull from a video call layout since the interface with button is quicly hidden. 
	 */
	public void hangUpWithDoubleTap(){
		doubleTapElement(hangUpButton, driver);
	}
} public class RiotIncomingCallPageObjects extends TestUtilities {
	private IOSDriver<MobileElement> driver;
	public RiotIncomingCallPageObjects(AppiumDriver<MobileElement> myDriver){
		driver= (IOSDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(driver), this);
		try {
			waitUntilDisplayed(driver,"AppDelegateIncomingCallAlert", true, 10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	@iOSFindBy(xpath="AppDelegateIncomingCallAlert")
	public MobileElement incomingCallAlert;
	@iOSFindBy(accessibility="AppDelegateIncomingCallAlertActionDecline")
	public MobileElement declineCallButton;
	@iOSFindBy(accessibility="AppDelegateIncomingCallAlertActionAccept")
	public MobileElement acceptCallButton;

	
	public void checkIncomingCallView(Boolean isDisplayed, String callerName, String voiceOrVideo) throws InterruptedException{
//		String messagePendingViewPresent;
//		if(isDisplayed){
//			messagePendingViewPresent="Incoming call view isn't displayed";
//		}else{
//			messagePendingViewPresent="Incoming call view is displayed";
//		}
		//Assert.assertTrue(waitUntilDisplayed(driver, "//XCUIElementTypeAlert[contains(@name,'Incoming voice call')]", isDisplayed, 5)==isDisplayed, messagePendingViewPresent);
		if(isDisplayed){
			//Assert.assertTrue(waitUntilDisplayed(driver, "XCUIElementTypeAlert[@name='AppDelegateIncomingCallAlert']//XCUIElementTypeStaticText[@value='Incoming voice call from "+callerName+"']", true, 5), "Incoming call message is wrong.");
			Assert.assertTrue(waitUntilDisplayed(driver, "Incoming "+voiceOrVideo+" call from "+callerName, true, 5), "Incoming call message is wrong.");
		}
	}

} public class RiotRoomDetailsPageObjects extends TestUtilities{
	private AppiumDriver<MobileElement> driver;
	public RiotRoomDetailsPageObjects(AppiumDriver<MobileElement> myDriver) {
		driver= myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(driver), this);
		try {
			waitUntilDisplayed((IOSDriver<MobileElement>) driver,"Room Details", true, 5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/*
	 * NAVIGATION BAR
	 */
	@iOSFindBy(accessibility="Room Details")
	public MobileElement navigationBar;
	@iOSFindBy(accessibility="Back")
	public MobileElement menuBackButton;
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeOther/XCUIElementTypeOther[2]/XCUIElementTypeNavigationBar/XCUIElementTypeStaticText")
	public MobileElement roomDetailsStaticText;
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeNavigationBar/XCUIElementTypeButton[@name='Cancel']")
	public MobileElement roomDetailsCancelButton;
	@iOSFindBy(accessibility="Done")
	public MobileElement roomDetailsDoneButton;
	
	/*
	 * COMMON.
	 */
	@iOSFindBy(accessibility="SegmentedVCUITableViewContainer")
	public MobileElement segmentedTable;
	
	/*
	 * TABS: MEMBERS, FILES, SETTINGS
	 */
	/**
	 * Contains the 3 tabs : members, files, settings. </br>
	 */
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeOther[count(XCUIElementTypeStaticText)=3]")
	public MobileElement tabsTypeOther;
	@iOSFindBy(accessibility="SegmentedVCSectionLabel0")
	public MobileElement membersTab;
	@iOSFindBy(accessibility="SegmentedVCSectionLabel1")
	public MobileElement filesTab;
	@iOSFindBy(accessibility="SegmentedVCSectionLabel2")
	public MobileElement settingsTab;

	
	/**
	 * Loading wheel.
	 */
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeActivityIndicator[@name='In progress']")
	public MobileElement loadingWheelActivityIndicator;
	/**
	 * Wait until the loading wheel isn't displayed anymore. </br>
	 * Can be used after hitting Done on the navigation bar.
	 * @throws InterruptedException 
	 */
	public void waitUntilDetailsDone() throws InterruptedException{
		waitUntilDisplayed(driver, "//*[@name='In progress']", false, 10);
	}
	/*
	 * MEMBERS TAB
	 */
	//FILTER BAR
	@iOSFindBy(accessibility="RoomParticipantsVCSearchBarView")
	public MobileElement searchInviteBarView;
	@iOSFindBy(accessibility="RoomParticipantsVCSearchBarView")
	public MobileElement searchInviteSearchField;
	@iOSFindBy(accessibility="Clear text")
	public MobileElement clearFilteredBarButton;
	
	//MEMBERS LIST
	@iOSFindBy(accessibility="RoomParticipantsVCTableView")
	public MobileElement membersTableView;
	@iOSFindBy(accessibility="ContactTableViewCell")
	public List<MobileElement> membersList;
	@iOSFindBy(accessibility="add_participant")
	public MobileElement addParticipantButton;
	public List<MobileElement> getCategories(){
		
		return membersTableView.findElementsByClassName("XCUIElementTypeOther");
	}
	
	/**
	 * Add a participant from room details, Members tab.
	 * @param participant2Adress
	 */
	public void addParticipant(String participant2Adress) {
		addParticipantButton.click();
		RiotContactPickerPageObjects contactPicker = new RiotContactPickerPageObjects(driver);
		contactPicker.searchAndSelectMember(participant2Adress);
	}
	
	/**
	 * Return a member relativelayout using name of the member.
	 * @param memberName
	 * @return
	 */
	public MobileElement getMemberByName(String memberName){
		try {
			return membersTableView.findElementByXPath("//XCUIElementTypeCell[@name='ContactTableViewCell']/XCUIElementTypeStaticText[@name='MemberDisplayName' and @value='"+memberName+"']/..");	
		} catch (Exception e) {
			System.out.println("No member found with name '"+memberName+"'");
			return null;
		}
		
	}
	
	/**
	 * From the room details people tab, enter a text on the filter room members edittext.
	 * @param filter
	 */
	public void filterOnRoomMembersList(String filter){
		searchInviteBarView.setValue(filter);
	}
	/**
	 * Return the displayname from a filtered member from the people tab.
	 * @param member
	 * @return
	 */
	public String getDisplayNameOfMemberFromPeopleTab(MobileElement member){
		try {
			return member.findElementByAccessibilityId("MemberDisplayName").getText();
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * Swipe to the left on a member item, then hit the "eject" button.</br>
	 * Wait until the progress bar is gone.
	 * @param memberItem
	 * @throws InterruptedException 
	 */
	public void removeMemberWithSwipeOnItem(MobileElement memberItem) throws InterruptedException{
		int x = memberItem.getLocation().getX();
		int y= memberItem.getLocation().getY();
		int witdthX=memberItem.getSize().getWidth();
		int xFirst=x+witdthX-80;
//		float xEndF=(float) (0.3*witdthX);
//		int xEnd=(int)xEndF;
		//Swipe to the left on the item.
		driver.swipe(witdthX+5,y, xFirst-50,y,500);
		//Hit on eject button
		memberItem.findElementByClassName("XCUIElementTypeButton").click();
		//hit on remove confirmation button from dialog alert
		alertRemoveConfirmationRemoveButton.click();
		
//		waitUntilDisplayed(driver, "android:id/parentPanel", true, 10);
//		Assert.assertEquals(inputAndroidDialogNameTextView.getText(), "Remove?");
//		inputDialogOkButton.click();
//		waitUntilDisplayed(driver, "//android.widget.ProgressBar", false, 10);
	}
	
	//Remove alert dialog
	@iOSFindBy(accessibility="RoomParticipantsVCKickAlertActionRemove")
	public MobileElement alertRemoveConfirmationRemoveButton;
	@iOSFindBy(accessibility="RoomParticipantsVCKickAlertActionCancel")
	public MobileElement alertRemoveConfirmationCancelButton;
	
	/**
	 * Wait until INVITED categorie is displayed.</br>
	 * Can be used to wait until an invitation is done.
	 * @throws InterruptedException
	 */
	public void waitUntilInvitedCategorieIsDisplayed(Boolean invitedCategorieDisplayed) throws InterruptedException{
		int maxToWait=30;
		int timeWaited=0;
		int size;
		if(invitedCategorieDisplayed){
			size=1;
		}else{
			size=0;
		}
		waitUntilDisplayed(driver, "RoomParticipantsVCTableView", true, 5);
		while (getCategories().size()!=size && timeWaited <=maxToWait) {
			Thread.sleep(500);
			timeWaited++;
		}
		if(timeWaited>=maxToWait){
			Assert.fail();
			System.out.println("INVITED categorie isn't displayed after "+maxToWait+"s.");
		}
	}
	
	/*
	 * FILES TAB
	 */
	@iOSFindBy(accessibility="FilesSearchTableViewCell")
	public List<MobileElement> attachedFilesList;
	
	
	/*
	 * SETTINGS TAB
	 */
	@iOSFindBy(xpath="//XCUIElementTypeTable/XCUIElementTypeCell[2]/XCUIElementTypeTextField")
	public MobileElement roomNameTextField;
	
	@iOSFindBy(accessibility="Leave")
	public MobileElement leaveButton;
	@iOSFindBy(accessibility="RoomSettingsVCLeaveAlertActionLeave")
	public MobileElement confirmLeaveFromAlertButton;
	@iOSFindBy(accessibility="RoomSettingsVCLeaveAlertActionCancel")
	public MobileElement confirmCancelFromAlertButton;
	
	public void changeRoomName(String roomName){
		roomNameTextField.clear();
		roomNameTextField.setValue(roomName+"\n");
		//roomNameTextField.sendKeys(Keys.ENTER);
	}
	//ADVANCED PART
	@iOSFindBy(xpath="//XCUIElementTypeTable/XCUIElementTypeCell/XCUIElementTypeSwitch[@name='Enable encryption (warning: cannot be disabled again!)']")
	public MobileElement enableEncryptionSwitch;
	/**
	 * Switch off encryption on a room. The switch need to be focused.
	 * </br> Click on OK Button.
	 */
	public void enableEncryption(){
		enableEncryptionSwitch.click();
		Assert.assertTrue(warningAlert.isDisplayed());
		warningAlertOkButton.click();
	}
		//Warning alert
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeAlert[@name='Warning!']")
	public MobileElement warningAlert;
	@iOSFindBy(accessibility="RoomSettingsVCEnableEncryptionAlertActionCancel")
	public MobileElement warningAlertCancelButton;
	@iOSFindBy(accessibility="RoomSettingsVCEnableEncryptionAlertActionOK")
	public MobileElement warningAlertOkButton;
	

} public class RiotRoomPageObjects extends TestUtilities{
	private IOSDriver<MobileElement> driver;
	public RiotRoomPageObjects(AppiumDriver<MobileElement> myDriver) {
		driver= (IOSDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(driver), this);
		try {
			waitUntilDisplayed((IOSDriver<MobileElement>) driver,"RoomVCView", true, 10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
 /*
  * NAVIGATION BAR
  */
	@iOSFindBy(accessibility="Messages")
	public MobileElement navigationBar;
	@iOSFindBy(accessibility="Back")
	public MobileElement menuBackButton;
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeNavigationBar[@name=\"Messages\"]/XCUIElementTypeOther[1]//XCUIElementTypeStaticText")
	public MobileElement badgeNumberStaticText;
	@iOSFindBy(accessibility="DisplayNameTextField")
	public MobileElement roomNameStaticText;
	@iOSFindBy(accessibility="RoomDetailsIconImageView")
	public MobileElement openRoomDetails;
	@iOSFindBy(accessibility="search icon")
	public MobileElement searchInRoomButton;
	
	/*
	 * COLLAPSED NAVIGATION BAR
	 */
	@iOSFindBy(accessibility="RoomVCExpandedHeaderContainer")
	public MobileElement collapsedRoomDetailsContainer;
	@iOSFindBy(accessibility="RoomDetailsIconImageView")
	public MobileElement openRoomDetailsFromCollapsedBar;
	@iOSFindBy(accessibility="RoomMembers")
	public MobileElement inviteMembersLink;
	@iOSFindBy(accessibility="RoomTopic")
	public MobileElement roomTopicStaticText;
	@iOSFindBy(accessibility="RoomMembersDetailsIcon")
	public MobileElement roomMembersDetailIcon;
	
	
	/*
	 * PREVIEW LAYOUT
	 */
	 @iOSFindBy(accessibility="RoomVCPreviewHeaderContainer")
	 public MobileElement roomPreviewContainer;
	 @iOSFindBy(accessibility="MainHeaderBackground")
	 public MobileElement roomPreviewBackground;
	 @iOSFindBy(accessibility="PreviewLabel")
	 public MobileElement roomPreviewLabel;
	 @iOSFindBy(accessibility="RightButton")
	 public MobileElement joinRoomButton;
	 @iOSFindBy(accessibility="LeftButton")
	 public MobileElement declineRoomButton;
	 
	/**
	 * Check the room preview layout after accepting an invitation.
	 * @throws InterruptedException 
	 */
	public void checkPreviewRoomLayout(String roomName) throws InterruptedException{
		Assert.assertEquals(roomPreviewContainer.findElementByAccessibilityId("DisplayNameTextField").getText(), roomName);
		Assert.assertTrue(roomPreviewLabel.getText().contains("You have been invited to join this room by"));
		Assert.assertEquals(joinRoomButton.getText(), "Join");
		Assert.assertEquals(declineRoomButton.getText(), "Decline");
	}
	
	/*
	 * PENDING CALL VIEW
	 */
	public MobileElement getPendingCallView(String status) throws WebDriverException, InterruptedException{
		if(waitUntilDisplayed(driver, status, true, 5)) {
			return driver.findElementByAccessibilityId(status);
			}
		else{
			return null;
		}
	}
	
	public void checkPendingCallView(Boolean displayed,String status) throws InterruptedException {
		String messagePendingViewPresent;
		//Boolean statusFound=false;
		if(displayed){
			messagePendingViewPresent="Pending view isn't displayed";
		}else{
			messagePendingViewPresent="Pending view is displayed";
		}
//		try {
//			driver.findElementByAccessibilityId(status);
			
//			statusFound=true;
//		} catch (Exception e) {
//			// TODO: handle exception
//			statusFound=false;
//		}
		Assert.assertEquals(waitUntilDisplayed(driver, status, displayed, 5), displayed, messagePendingViewPresent);
		
	}
	/*
	 * MESSAGES
	 */
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeTable[1]")
	public MobileElement bubblesTable;
	@iOSFindBy(accessibility="RoomBubbleCell")
	public List<MobileElement> bubblesList;

	/**
	 * Return the last bubble as a mobileElement.
	 */
	public MobileElement getLastBubble(){
		if (bubblesList.size()>0){
			return bubblesList.get(bubblesList.size()-1);
		}
		else{
			return null;
		}
	}
	/**
	 * Return the last bubble as a mobileElement using xpath. May be faster than getLastBubble() if there is a lot of bubbles in the room.
	 */
	public MobileElement getLastBubble_bis(){
		return bubblesTable.findElementByXPath("//XCUIElementTypeCell[last()]");
	}
	
	/**
	 * Return a bubble by his index.
	 */
	public MobileElement getBubbleByIndex(int indexPost){
		return bubblesList.get(indexPost);
	}
	
	/**
	 * Return the author of a bubble as a MobileElement.
	 * @param bubble
	 * @return
	 */
	public MobileElement getAuthorFromBubble(MobileElement bubble){
		return bubble.findElementByAccessibilityId("UserNameLabel");
	}
	
	/**
	 * Return the content text of a bubble as a MobileElement.
	 */
	public MobileElement getTextViewFromBubble(MobileElement bubble){
		return bubble.findElementByAccessibilityId("MessageTextView");
	}
	/**
	 * Return the content text of a bubble as a MobileElement.
	 */
	public MobileElement getProgressStatsFromBubble(MobileElement bubble){
		try {
			return bubble.findElementByAccessibilityId("ProgressStats");
		} catch (Exception e) {
			// TODO: handle exception
			return null;
		}
	}
	
	/**
	 * Return the content text of a bubble as a MobileElement.
	 */
	public MobileElement getTimeStampByBubble(MobileElement bubble){
		try {
			return bubble.findElementByAccessibilityId("timestampLabel");
		} catch (Exception e) {
			// TODO: handle exception
			return null;
		}
	}
	
	/**
	 * Wait until progress bar in the post is still displayed.
	 * @param bubbleCell
	 * @param maxToWait
	 * @throws InterruptedException
	 */
	public Boolean waitAndCheckForMediaToBeUploaded(MobileElement bubbleCell, int maxToWait) throws InterruptedException {
		float secondsWaited=0;Boolean uploaded=false;
		while (getProgressStatsFromBubble(bubbleCell)!=null && secondsWaited<maxToWait) {
			Thread.sleep(500);
			secondsWaited=(float) (secondsWaited+0.5);
		}
		if(getProgressStatsFromBubble(bubbleCell)==null){
			uploaded=true;
			System.out.println("Media uploaded after "+secondsWaited+" s.");
		}
		return uploaded;
	}
	
	/**
	 * Wait for the bubbles lists to be not empty.
	 * @throws InterruptedException
	 */
	public void waitForBubblesToBeDisplayed() throws InterruptedException{
		int maxSecondsToWait=10;
		float secondsWaited=0;
		while (bubblesList.size()==0 && secondsWaited<maxSecondsToWait) {
			Thread.sleep(500);secondsWaited=(float) (secondsWaited+0.5);
		}
	}
	
	/**
	 * Wait for a new post to arrive in the room.
	 * @param maxSecondsToWait
	 * @throws InterruptedException 
	 */
	public void waitForReceivingNewMessage(int maxSecondsToWait) throws InterruptedException {
		int sizeAtBegining=bubblesList.size();
		float secondsWaited=0;
		while (bubblesList.size()==sizeAtBegining && secondsWaited<maxSecondsToWait) {
			Thread.sleep(500);secondsWaited=(float) (secondsWaited+0.5);
		}
		System.out.println("Time waited for new messages to arrive: "+secondsWaited+ " seconds.");
	}
	
	/*
	 * SELECT MEDIA SIZE MENU
	 */
	@iOSFindBy(accessibility="Do you want to send as:")
	public MobileElement selectSizeMenuSheet;
	/**
	 * 'Send' as item list. Contains small -> actual size items + cancel item.
	 */
	@iOSFindBy(xpath="//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeSheet//XCUIElementTypeCollectionView/XCUIElementTypeCell")
	public MobileElement sendAsItemList;
	
	/*
	 * NOTIFICATION AREA
	 */
	@iOSFindBy(accessibility="RoomVCActivitiesContainer")
	public MobileElement roomNotificationArea;
	@iOSFindBy(accessibility="RoomExtrasInfosView")
	public MobileElement roomNotificationArea2;
	
	/**
	 * Not sure it works. Better getNotificationMessage().
	 */
	@iOSFindBy(accessibility="RoomActivitiesViewMessageLabel")
	public MobileElement notificationMessage;
	
	public MobileElement getNotificationMessage(){
		return roomNotificationArea2.findElementByClassName("XCUIElementTypeTextView");
	}
	
	/**
	 * Click on "Resend All" link on the messages not sent due to unknown devices messages, on the notification area.
	 */
	public void clickOnResendAllLinkFromNotificationArea(){
		notificationMessage.getSize().getWidth();notificationMessage.getCenter();
		int xLink=notificationMessage.getCenter().getX();
		//int yLink=notificationMessage.getLocation().getY()+(notificationMessage.getSize().getHeight()/4)*3;
		int yLink=notificationMessage.getLocation().getY()+(notificationMessage.getSize().getHeight()/4)*2+5;
		driver.tap(1, xLink, yLink, 500);
	}
	
	/*
	 * BOTTOM
	 */
	@iOSFindBy(accessibility="AttachButton")
	public MobileElement uploadButton;
	@iOSFindBy(accessibility="SendButton")
	public MobileElement sendButton;
	@iOSFindBy(accessibility="VoiceCallButton")
	public MobileElement voiceCallButton;
	@iOSFindBy(accessibility="HangupCallButton")
	public MobileElement hangUpCallButton;
	@iOSFindBy(accessibility="EncryptedRoomIcon")
	public MobileElement e2eIconImage;
	@iOSFindBy(accessibility="GrowingTextView")
	public MobileElement sendKeyTextView;
	
	/*
	 * MENU VOICE and VIDEO.
	 */
	/**
	 * Menu opened after hitting the call button. Proposes voice or video call.
	 */
	@iOSFindBy(className="XCUIElementTypeCollectionView")
	public MobileElement menuCallChoiceCollectionView;
	@iOSFindBy(accessibility="Voice")
	public MobileElement voiceItemMenu;
	@iOSFindBy(accessibility="Video")
	public MobileElement videoItemMenu;
	
	/**
	 * Start a voice call from the room page.
	 * @throws InterruptedException 
	 */
	public void startVoiceCall() throws InterruptedException {
		voiceCallButton.click();
		voiceItemMenu.click();
	}
	/**
	 * Start a voice call from the room page.
	 * @throws InterruptedException 
	 */
	public void startVideoCall() throws InterruptedException {
		voiceCallButton.click();
		videoItemMenu.click();
	}

	/**
	 * Check that a photo is present in a post by checking his dimension.
	 * @param post
	 */
	public void checkThatPhotoIsPresentInPost(MobileElement post){
//		org.openqa.selenium.Dimension takenPhoto=this.getAttachedImageByPost(post).getSize();
//	    Assert.assertTrue(takenPhoto.height!=0 && takenPhoto.width!=0, "The unsent photo has null dimension");
	}
	/**
	 * Hit the upload button, take photo, then select a size.
	 * @param size
	 * @throws InterruptedException
	 */
	public void attachPhotoFromCamera(String size) throws InterruptedException {
		uploadButton.click();
		RiotCameraPageObjects cameraPage = new RiotCameraPageObjects(appiumFactory.getiOsDriver1());
		cameraPage.cameraCaptureButton.click();
		waitUntilDisplayed(driver, "OK", true, 10);
		cameraPage.okButton.click();
		getItemFromSendAsMenu(size).click();;
	}
	/**
	 * Return item from the "Send as menu"
	 * @param size : Original, Large, Medium, Small
	 * @return
	 */
	public MobileElement getItemFromSendAsMenu(String size){
		ExplicitWait(driver, selectSizeMenuSheet);
		return driver.findElementByXPath("//XCUIElementTypeApplication/XCUIElementTypeWindow//XCUIElementTypeSheet//XCUIElementTypeCollectionView/XCUIElementTypeCell/XCUIElementTypeButton[contains(@name,'"+size+"')]");
	}


	/**
	 * Type and send a message.
	 * @param msg
	 */
	public void sendAMessage(String msg) {
		sendKeyTextView.sendKeys(msg);
		sendButton.click();
	}
	
	/**
	 * From the room page, go into the details of the room and hit leave button.
	 */
	public void leaveRoom() {
		RiotRoomDetailsPageObjects details1=openDetailView();
		details1.settingsTab.click();
		details1.leaveButton.click();
		details1.confirmLeaveFromAlertButton.click();
		//details1= new RiotRoomDetailsPageObjects(driver);
//		try {
//			Thread.sleep(500);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		try {
			waitUntilDisplayed(driver, "Back", true, 5);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		menuBackButton.click();
	}
	/**
	 * Open the detail view from the page.</br>
	 * Return a RiotRoomDetailsPageObjects.
	 */
	public RiotRoomDetailsPageObjects openDetailView(){
		if(isRoomHeaderExpanded()==true){
			roomMembersDetailIcon.click();
		}else{
			openRoomDetails.click();
		}
		return new RiotRoomDetailsPageObjects(driver);
	}
	/**
	 * Return true if the room details is expanded and false if not.
	 * @return
	 */
	public Boolean isRoomHeaderExpanded(){
		if(collapsedRoomDetailsContainer.findElementByAccessibilityId("DisplayNameTextField").getText().equals("Room Name")){
			return false;
		}else{
			return true;
		}
	}

	/*
	 * ENCRYPTION
	 */
	@iOSFindBy(accessibility="RoomVCEncryptionAlert")
	public MobileElement WarningOnBetaEncryptionAlert;
	@iOSFindBy(accessibility="RoomVCEncryptionAlertActionOK")
	public MobileElement WarningOnBetaEncryptionOkButton;
	
	/**
	 * Close the warning alert about the beta state of encryption when user enters the first time in a room.
	 * @throws InterruptedException
	 */
	public void closeWarningAlertAboutBetaStateOfE2e() throws InterruptedException{
		if(waitUntilDisplayed(driver, "RoomVCEncryptionAlert", true, 1)){
			WarningOnBetaEncryptionOkButton.click();
		}
		
	}
} public class RiotUnknownDevicesListPageObjects extends TestUtilities{
	private AppiumDriver<MobileElement> driver;
	public RiotUnknownDevicesListPageObjects(AppiumDriver<MobileElement> myDriver) throws InterruptedException{
		driver=(IOSDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(myDriver), this);
		try {
			waitUntilDisplayed(driver,"UsersDevicesVCTitleStaticText", true, 5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/*
	 * NAVIGATION BAR
	 */
	@iOSFindBy(accessibility="Unknown devices")
	public MobileElement navigationBar;
	@iOSFindBy(accessibility="UsersDevicesVCTitleStaticText")
	public MobileElement titleStaticText;
	@iOSFindBy(accessibility="UsersDevicesVCDoneButton")
	public MobileElement doneButton;
	@iOSFindBy(accessibility="UsersDevicesVCCancelButton")
	public MobileElement cancelButton;
	
	
	/*
	 * BODY
	 */
	@iOSFindBy(accessibility="UsersDevicesVCDTableView")
	public MobileElement usersDeviceTableView;
	
	/**
	 * List of the items containing the unknown devices of a user.</br>
	 * Name of the user in the first and only XCUIElementTypeStaticText child of an item.
	 */
	public List<MobileElement> getUserNameSectionCollapsableList(){
		return usersDeviceTableView.findElementsByAccessibilityId("XCUIElementTypeOther");
	}
	
	/**
	 * List of unknown devices. An item contains the device name, the device id and the two buttons: verify/unverify, blacklist/unblacklist.
	 */
	@iOSFindBy(accessibility="DeviceTableViewCell")
	public List<MobileElement> devicesViewCellList;

	
	/**
	 * Return the device name + id of an item at indexDevice.
	 * @param indexDevice
	 * @return
	 */
	public String getDeviceNamePlusIdByIndex(int indexDevice){
		if(indexDevice<devicesViewCellList.size()){
			return devicesViewCellList.get(indexDevice).findElementByAccessibilityId("DeviceTableViewCellDeviceName").getText();
		}else{
			System.out.println("There is not device item at index "+indexDevice);
			return null;
		}
	}
	/**
	 * Return the device name of an item at indexDevice.
	 * @param indexDevice
	 * @return
	 */
	public String getDeviceNameByIndex(int indexDevice){
			String namePlusId= getDeviceNamePlusIdByIndex(indexDevice);
			String name=namePlusId.substring(0, namePlusId.indexOf("(")-1);
			return name;
	}
	
	/**
	 * Return the device id of an item at indexDevice.
	 * @param indexDevice
	 * @return
	 */
	public String getDeviceIDByIndex(int indexDevice){
		String namePlusId= getDeviceNamePlusIdByIndex(indexDevice);
		String id=namePlusId.substring(namePlusId.indexOf("(")+1,namePlusId.indexOf(")"));
		return id;
	}
	
	
	/**
	 * Hit the verify button of a device by his index position.
	 * @param indexDevice
	 */
	public MobileElement getVerifyDeviceButton(int indexDevice){
		if(indexDevice<devicesViewCellList.size()){
			return devicesViewCellList.get(indexDevice).findElementByAccessibilityId("DeviceTableViewCellVerifyButton");
		}else{
			System.out.println("There is not device item at index "+indexDevice);
			return null;
		}
	}
} public class RiotUnknownDevicesModalPageObjects extends TestUtilities{
	private AppiumDriver<MobileElement> driver;
	public RiotUnknownDevicesModalPageObjects(AppiumDriver<MobileElement> myDriver) throws InterruptedException{
		driver=(IOSDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(myDriver), this);
		try {
			waitUntilDisplayed(driver,"RoomVCUnknownDevicesAlert", true, 5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/*
	 * ALERT TITLE
	 */
	@iOSFindBy(accessibility="Room contains unknown devices")
	public MobileElement alertTitleTextView;
	
	/*
	 * ALERT BODY
	 */
	@iOSFindBy(accessibility="RoomVCUnknownDevicesAlert")
	public MobileElement alertBodyListView;
	
	/**
	 * Return the text view containing the main message.
	 */
	public MobileElement getAlertBodyMessageTextView(){
		return alertBodyListView.findElementsByClassName("XCUIElementTypeStaticText").get(2);
	}
	
	/*
	 * ALERT BOTTOM
	 */
	@Deprecated
	@iOSFindBy(accessibility="RoomVCUnknownDevicesAlertActionCancel")
	public MobileElement cancelButton;
	@iOSFindBy(accessibility="RoomVCUnknownDevicesAlertActionVerify...")
	public MobileElement verifyButton;
	@iOSFindBy(accessibility="RoomVCUnknownDevicesAlertActionSend Anyway")
	public MobileElement sendAnywayButton;
	
	public void checkUnknownDevicesModal(){
		Assert.assertEquals(alertTitleTextView.getText(), "Room contains unknown devices", "Modal title is wrong.");
		Assert.assertEquals(getAlertBodyMessageTextView().getText(), "This room contains unknown devices which have not been verified. This means there is no guarantee that the devices belong to the users they claim to. We recommend you go through the verification process for each device before continuing, but you can resend the message without verifying if you prefer.", "Modal main message is wrong.");
		//For whatever reason, the text of these 2 buttons isn't accessible.
//		Assert.assertEquals(cancelButton.getText(), "Cancel");
//		Assert.assertEquals(verifyButton.getText(), "Verify...");
	}
} public class RiotVerifyDevicePageObjects extends TestUtilities{
	private AppiumDriver<MobileElement> driver;
	public RiotVerifyDevicePageObjects(AppiumDriver<MobileElement> myDriver) {
		driver=(IOSDriver<MobileElement>) myDriver;
		PageFactory.initElements(new AppiumFieldDecorator(myDriver), this);
		try {
			waitUntilDisplayed(driver,"//XCUIElementTypeWindow/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther[2]", true, 5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/*
	 * ALERT BODY
	 */
	@iOSFindBy(className="XCUIElementTypeTextView")
	public MobileElement alertMainMessageTextView;
	
	/*
	 * ALERT BOTTOM
	 */
	@iOSFindBy(accessibility="Verify")
	public MobileElement alertVerifyButton;
	@iOSFindBy(accessibility="Cancel")
	public MobileElement alertCancelButton;
	
	/**
	 * Verify the alert title, messages and the device name, id and key.</br>
	 * Put these parameters as null if you don't want to test it.
	 * @param deviceName
	 * @param deviceId
	 * @param deviceKey
	 */
	public void checkVerifyDeviceAlert(String deviceName, String deviceId, String deviceKey){
		String mainMessage=alertMainMessageTextView.getText();
		Assert.assertTrue(mainMessage.contains("Verify device"));
		Assert.assertTrue(mainMessage.contains("To verify that this device can be trusted, please contact its owner using some other means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings for this device matches the key below:"));
		Assert.assertTrue(mainMessage.contains("If it matches, press the verify button below. If it doesnt, then someone else is intercepting this device and you probably want to press the blacklist button instead.\n\nIn future this verification process will be more sophisticated."));
		
		if(deviceName!=null){
			Assert.assertTrue(mainMessage.contains(deviceName), "Device name in the 'Verify device' alert isn't the one expected.");
		}else{
			String extractedDeviceName=mainMessage.substring(mainMessage.indexOf("Device name: ")+13, mainMessage.indexOf("Device ID: "));
			Assert.assertTrue(extractedDeviceName.length()>2);
		}
		if(deviceId!=null){
			Assert.assertTrue(mainMessage.contains(deviceId), "Device id in the 'Verify device' alert isn't the one expected.");
		}else{
			String extractedDeviceId=mainMessage.substring(mainMessage.indexOf("Device ID: ")+11, mainMessage.indexOf("Device key: "));
			Assert.assertTrue(extractedDeviceId.length()>2);
		}
		if(deviceKey!=null){
			Assert.assertTrue(mainMessage.contains(deviceKey), "Device key in the 'Verify device' alert isn't the one expected.");
		}else{
			String extractedDeviceKey=mainMessage.substring(mainMessage.indexOf("Device key: ")+12, mainMessage.indexOf("If it matches"));
			Assert.assertTrue(extractedDeviceKey.length()>2);
		}
	}
} public class RiotHomePageTabObjects extends RiotTabPageObjects{

	public RiotHomePageTabObjects(AppiumDriver<MobileElement> myDriver) throws InterruptedException {
		super(myDriver);
		PageFactory.initElements(new AppiumFieldDecorator(driver), this);
		Assert.assertTrue(waitUntilDisplayed((IOSDriver<MobileElement>) driver,"HomeVCView", true, 10),"HomePage tab isn't open.");
		//Instanciate protected properties from mother class with own and uniques values of this tab.
		super.roomsTableView=hpTabRoomsTableView;
		super.tabMainView=homePageTabView;
	}

	@iOSFindBy(accessibility="HomeVCView")
	public MobileElement homePageTabView;

	/*
	 * ROOMS LIST.
	 */
	/**
	 * Table view of rooms items. </br> Contains a list of 'RecentTableViewCell' cells.
	 */
	@iOSFindBy(accessibility="HomeVCTableView")
	public MobileElement hpTabRoomsTableView;
	
	/**
	 * TEMP !!!!!!!!!!
	 * Return a room as a MobileElement using his title.</br>
	 * Return null if not found.
	 * @param myRoomName
	 * @return
	 */
	public MobileElement getRoomByName(String myRoomName){
		try {
			return roomsTableView.findElementByXPath("//XCUIElementTypeCell/XCUIElementTypeStaticText[@name='TitleLabel' and @value='"+myRoomName+"']");
		} catch (Exception e) {
			System.out.println("No room found with name "+myRoomName);
			return null;
		}
	}
} public class Constant {
	public static final String FILE_TESTDATA = "testdata1.xlsx";
	/*
	 * APPIUM SERVERS
	 */
	public static final String SERVER1_ADDRESS="0.0.0.0";
	public static final String SERVER2_ADDRESS="127.0.0.1";
	public static final String APPIUM_COMMON_PORT="4723";
	public static final String WEBDRIVERAGENT_PORT="8080";
	public static final String SERVER1_HTTP_ADDRESS="http://"+SERVER1_ADDRESS+":"+APPIUM_COMMON_PORT+"/wd/hub";
	public static final String SERVER2_HTTP_ADDRESS="http://"+SERVER2_ADDRESS+":"+APPIUM_COMMON_PORT+"/wd/hub";

	public static final String getServer1HttpAddress() throws FileNotFoundException, YamlException{
		if("2"==ReadConfigFile.getInstance().getConfMap().get("starting_server_mode"))
			return AppiumServerStartAndStopService.service_url1;
		else
			return SERVER1_HTTP_ADDRESS;
	}

	public static final String getServer2HttpAddress() throws FileNotFoundException, YamlException{
		if("2"==ReadConfigFile.getInstance().getConfMap().get("starting_server_mode"))
			return AppiumServerStartAndStopService.service_url2;
		else
			return SERVER2_HTTP_ADDRESS;
	}

	/*
	 * CONF
	 */
	public static final String CONFIG_FILE = "src/test/java/config/config.yaml";
	public static final String DEVICES_CONFIG_FILE ="src/test/java/config/devices.yaml";

	/*
	 * RIOT
	 */
	public static final String APPLICATION_NAME = "RIOT";
	/*
	 * 			iOS-specific
	 */
	public static final String APP_BUNDLE_ID = "im.vector.app";
	public static final String PATH_TO_IOS_IPA="/buildipa/riot-ios/out/Vector.ipa";
	/*
	 * 			Android-specific
	 */
	public static final String PACKAGE_APP_NAME = "im.vector.alpha";
	public static final String APPLICATION_LOGIN_ACTIVITY="im.vector.activity.LoginActivity";
	public static final String PATH_TO_ANDROID_APK="/buildapk/riot-android/out/Vector.apk";


	/*
	 * NODE JS AND APPIUM
	 */
	public static final String PATH_TO_NODE_DIRECTORY="/usr/local/bin/node";
	public static final String PATH_TO_APPIUM_JAVASCRIPT="/usr/local/lib/node_modules/appium/build/lib/main.js";
	/*
	 * MISC 
	 */
	public static final String PATH_TESTDATA = "src//test//resources//testDatas//";
	public static final String DEFAULT_USERNAME="riotuser2";
	public static final String DEFAULT_USERPWD="riotuser";
	public static final String DEFAULT_USERADRESS="@riotuser2:matrix.org";
	public static final String DEFAULT_MATRIX_SERVER_URL="https://matrix.org";
	public static final String DEFAULT_MATRIX_SERVER="matrix.org";
	public static final String DEFAULT_IDENTITY_SERVER_URL="https://vector.im";

	/*
	 * E2E ENCRYPTION
	 */
	public static final String ENCRYPTION_TURNEDON_EVENT="turned on end-to-end encryption";
	public static final String ENCRYPTION_UNKNOWN_SESSION_ID_MSG="** Unable to decrypt: The sender's device has not sent us the keys for this message. **";
} public abstract class RiotParentTest extends TestUtilities {
	public static AppiumFactory appiumFactory=AppiumFactory.getInstance();

	@BeforeGroups(groups="1driver_android")
	public void setUp1AndroidDriver() throws Exception{
		//Start appium server 1 if necessary.
		startAppiumServer1();

		//Create android driver 1 if necessary
		//if(appiumFactory.getAndroidDriver1()==null || appiumFactory.getAndroidDriver1()!=null && appiumFactory.getAndroidDriver1().getSessionId()==null){
		if(appiumFactory.getAndroidDriver1()==null || appiumFactory.getAndroidDriver1().getSessionId()==null){
			Map<String, String> androidDevice1=ReadConfigFile.getInstance().getDevicesMap().get("androiddevice1");
			DesiredCapabilities capabilities = new DesiredCapabilities();
			capabilities.setCapability(MobileCapabilityType.UDID,androidDevice1.get(MobileCapabilityType.UDID));
			capabilities.setCapability(MobileCapabilityType.DEVICE_NAME,androidDevice1.get(MobileCapabilityType.DEVICE_NAME));
			capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME,androidDevice1.get(MobileCapabilityType.PLATFORM_NAME));
			capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, androidDevice1.get(MobileCapabilityType.PLATFORM_VERSION));
			capabilities.setCapability("appPackage", Constant.PACKAGE_APP_NAME);
			capabilities.setCapability("appActivity", Constant.APPLICATION_LOGIN_ACTIVITY);
			capabilities.setCapability(MobileCapabilityType.NO_RESET, true);
			capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);
			capabilities.setCapability(MobileCapabilityType.FULL_RESET, false);
			//Set android driver 1
			appiumFactory.setAndroidDriver1(new URL(Constant.getServer1HttpAddress()), capabilities);
			System.out.println("Application "+Constant.PACKAGE_APP_NAME+" started on device "+capabilities.getCapability(MobileCapabilityType.DEVICE_NAME) +" with AppiumDriver 1.");	
		}
	}

	/**
	 * @throws Exception
	 */
	@BeforeGroups(groups="2drivers_android")
	public void setUp2AndroidDrivers() throws Exception{
		//Start the two appium's servers if necessary.
		start2AppiumServers();

		Map<String, String> androidDevice1=ReadConfigFile.getInstance().getDevicesMap().get("androiddevice1");
		Map<String, String> androidDevice2=ReadConfigFile.getInstance().getDevicesMap().get("androiddevice2");

		//Create android driver 1 if necessary
		if(appiumFactory.getAndroidDriver1()==null || appiumFactory.getAndroidDriver1().getSessionId()==null){
			DesiredCapabilities capabilities1 = new DesiredCapabilities();
			capabilities1.setCapability(MobileCapabilityType.UDID,androidDevice1.get(MobileCapabilityType.UDID));
			capabilities1.setCapability(MobileCapabilityType.DEVICE_NAME,androidDevice1.get(MobileCapabilityType.DEVICE_NAME));
			capabilities1.setCapability(MobileCapabilityType.PLATFORM_NAME,androidDevice1.get(MobileCapabilityType.PLATFORM_NAME));
			capabilities1.setCapability(MobileCapabilityType.PLATFORM_VERSION, androidDevice1.get(MobileCapabilityType.PLATFORM_VERSION));
			capabilities1.setCapability("appPackage", Constant.PACKAGE_APP_NAME);
			capabilities1.setCapability("appActivity", Constant.APPLICATION_LOGIN_ACTIVITY);
			capabilities1.setCapability(MobileCapabilityType.NO_RESET, true);
			capabilities1.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "1200");
			capabilities1.setCapability(MobileCapabilityType.FULL_RESET, false);

			appiumFactory.setAndroidDriver1(new URL(Constant.getServer1HttpAddress()), capabilities1);
			System.out.println("Application "+Constant.APPLICATION_NAME+" started on ANDROID device "+capabilities1.getCapability(MobileCapabilityType.DEVICE_NAME) +" with DRIVER 1.");	
		}

		if(appiumFactory.getAndroidDriver2()==null || appiumFactory.getAndroidDriver2().getSessionId()==null){
			DesiredCapabilities capabilities2 = new DesiredCapabilities();
			capabilities2.setCapability(MobileCapabilityType.UDID,androidDevice2.get(MobileCapabilityType.UDID));
			capabilities2.setCapability(MobileCapabilityType.DEVICE_NAME,androidDevice2.get(MobileCapabilityType.DEVICE_NAME));
			capabilities2.setCapability(MobileCapabilityType.PLATFORM_NAME,androidDevice2.get(MobileCapabilityType.PLATFORM_NAME));
			capabilities2.setCapability(MobileCapabilityType.PLATFORM_VERSION, androidDevice2.get(MobileCapabilityType.PLATFORM_VERSION));
			capabilities2.setCapability("appPackage", Constant.PACKAGE_APP_NAME);
			capabilities2.setCapability("appActivity", Constant.APPLICATION_LOGIN_ACTIVITY);
			capabilities2.setCapability(MobileCapabilityType.NO_RESET, true);
			capabilities2.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "1200");
			capabilities2.setCapability(MobileCapabilityType.FULL_RESET, false);
			appiumFactory.setAndroidDriver2(new URL(Constant.getServer2HttpAddress()), capabilities2);
			System.out.println("Application "+Constant.APPLICATION_NAME+" started on ANDROID device "+capabilities2.getCapability(MobileCapabilityType.DEVICE_NAME) +" with DRIVER 2.");
		}
	}

	//	@AfterGroups(groups="1driver_android")
	//	public void tearDownAndroidDriver1() throws Exception{
	//		appiumFactory.getAndroidDriver1().quit();
	//		System.out.println("Android DRIVER 1 quitted on ANDROID device "+ReadConfigFile.getInstance().getDevicesMap().get("androiddevice1").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");
	//		System.out.println("session id driver 1 after quitting :"+appiumFactory.getAndroidDriver1().getSessionId());
	//		//Stop appium server1.
	//		stopAppiumServer1();
	//	}
	//
	//	@AfterGroups(groups={"2drivers_android"}, alwaysRun=true)
	//	public void tearDown2AndroidDrivers() throws Exception{
	//		appiumFactory.getAndroidDriver1().quit();
	//		System.out.println("Android DRIVER 1 quitted on ANDROID device "+ReadConfigFile.getInstance().getDevicesMap().get("androiddevice1").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");
	//		appiumFactory.getAndroidDriver2().quit();
	//		System.out.println("Android DRIVER 2 quitted on ANDROID device "+ReadConfigFile.getInstance().getDevicesMap().get("androiddevice2").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");
	//		System.out.println("session id driver 1 after quitting :"+appiumFactory.getAndroidDriver1().getSessionId());
	//		System.out.println("session id driver 2 after quitting :"+appiumFactory.getAndroidDriver2().getSessionId());
	//		//Stop the two appium's servers.
	//		stop2AppiumServers();
	//	}

	@AfterGroups(groups={"2drivers_android","1driver_android","1driver_ios","2drivers_ios"})
	public void tearDownAllDrivers() throws Exception{
		if(null!=appiumFactory.getAndroidDriver1()){
			appiumFactory.getAndroidDriver1().quit();
			System.out.println("Android DRIVER 1 quitted on ANDROID device "+ReadConfigFile.getInstance().getDevicesMap().get("androiddevice1").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");	
		}
		if(null!=appiumFactory.getAndroidDriver2()){
			appiumFactory.getAndroidDriver2().quit();
			System.out.println("Android DRIVER 2 quitted on ANDROID device "+ReadConfigFile.getInstance().getDevicesMap().get("androiddevice2").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");	
		}
		if(null!=appiumFactory.getiOsDriver1()){
			appiumFactory.getiOsDriver1().quit();
			System.out.println("Ios DRIVER 1 quitted on iOS device "+ReadConfigFile.getInstance().getDevicesMap().get("iosdevice1").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");	
		}
		if(null!=appiumFactory.getiOsDriver2()){
			appiumFactory.getiOsDriver2().quit();
			System.out.println("Ios DRIVER 2 quitted on iOS device "+ReadConfigFile.getInstance().getDevicesMap().get("iosdevice2").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");	
		}
		//Stop the two appium's servers.
		stop2AppiumServers();
	}

	@BeforeGroups(groups="1driver_ios")
	public void setUp1IosDriver() throws Exception{
		//Start appium server 1 if necessary.
		startAppiumServer1();

		//Create ios driver 1 if necessary
		if(appiumFactory.getiOsDriver1()==null || appiumFactory.getiOsDriver1().getSessionId()==null){
			Map<String, String> iosDevice1=ReadConfigFile.getInstance().getDevicesMap().get("iosdevice1");
			DesiredCapabilities capabilities = new DesiredCapabilities();
			capabilities.setCapability(MobileCapabilityType.UDID, iosDevice1.get(MobileCapabilityType.UDID));
			capabilities.setCapability(MobileCapabilityType.DEVICE_NAME,iosDevice1.get(MobileCapabilityType.DEVICE_NAME));
			capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME,iosDevice1.get(MobileCapabilityType.PLATFORM_NAME));
			capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, iosDevice1.get(MobileCapabilityType.PLATFORM_VERSION));
			capabilities.setCapability(IOSMobileCapabilityType.BUNDLE_ID, "im.vector.app");
			capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME,iosDevice1.get(MobileCapabilityType.AUTOMATION_NAME));
			capabilities.setCapability(MobileCapabilityType.NO_RESET, true);
			capabilities.setCapability(MobileCapabilityType.FULL_RESET, false);
			capabilities.setCapability("xcodeOrgId", ReadConfigFile.getInstance().getConfMap().get("development_team"));
			capabilities.setCapability("xcodeSigningId", ReadConfigFile.getInstance().getConfMap().get("code_sign_identity"));
			//capabilities.setCapability("xcodeConfigFile", "/usr/local/lib/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/Configurations/ProjectSettings.xcconfig");
			//capabilities.setCapability("keychainPath","/Users/matrix/Library/Keychains/appiumKeychain.keychain");
			//capabilities.setCapability("keychainPassword","appium6754");
			capabilities.setCapability("autoDismissAlerts", false);
			capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);

			appiumFactory.setiOSDriver1(new URL(Constant.getServer1HttpAddress()), capabilities);
			System.out.println("Application "+Constant.APPLICATION_NAME+" started on IOS device "+capabilities.getCapability(MobileCapabilityType.DEVICE_NAME) +" with DRIVER 1.");
		}
	}

	@BeforeGroups(groups="1driver_ios_install")
	public void setUp1IosDriverForInstallation() throws Exception{
		//Start appium server 1 if necessary.
		startAppiumServer1();
		Map<String, String> iosDevice1=ReadConfigFile.getInstance().getDevicesMap().get("iosdevice1");

		DesiredCapabilities capabilities = new DesiredCapabilities();
		capabilities.setCapability(MobileCapabilityType.UDID, iosDevice1.get(MobileCapabilityType.UDID));
		capabilities.setCapability(MobileCapabilityType.DEVICE_NAME,iosDevice1.get(MobileCapabilityType.DEVICE_NAME));
		capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME,iosDevice1.get(MobileCapabilityType.PLATFORM_NAME));
		capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, iosDevice1.get(MobileCapabilityType.PLATFORM_VERSION));
		capabilities.setCapability(MobileCapabilityType.APP, System.getProperty("user.dir")+Constant.PATH_TO_IOS_IPA);
		//capabilities.setCapability("bundleId", "im.vector.app");
		//XCUITest is used because Appium Ios driver doesn't support xcode version 8.0
		capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME,iosDevice1.get(MobileCapabilityType.AUTOMATION_NAME));
		capabilities.setCapability(MobileCapabilityType.NO_RESET, true);
		capabilities.setCapability(MobileCapabilityType.FULL_RESET, false);
		capabilities.setCapability("xcodeOrgId", ReadConfigFile.getInstance().getConfMap().get("development_team"));
		capabilities.setCapability("xcodeSigningId", ReadConfigFile.getInstance().getConfMap().get("code_sign_identity"));
		capabilities.setCapability(IOSMobileCapabilityType.AUTO_DISMISS_ALERTS, false);
		capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);
		//		capabilities.setCapability("autoWebview", true);

		AppiumFactory appiumFactory=AppiumFactory.getInstance();
		appiumFactory.setiOSDriver1(new URL(Constant.getServer1HttpAddress()), capabilities);
		System.out.println("Application "+Constant.APPLICATION_NAME+" started on IOS device "+capabilities.getCapability(MobileCapabilityType.DEVICE_NAME) +" with DRIVER 1.");
	}

	@BeforeGroups(groups="2drivers_ios")
	public void setUp2IosDriver() throws Exception{
		//Start the two appium's servers if necessary.
		Boolean iosDriver1NeedToStart=false;
		start2AppiumServers();

		//Create ios driver 1 if necessary
		if(appiumFactory.getiOsDriver1()==null || appiumFactory.getiOsDriver1().getSessionId()==null){
			iosDriver1NeedToStart=true;
			Map<String, String> iosDevice1=ReadConfigFile.getInstance().getDevicesMap().get("iosdevice1");
			DesiredCapabilities capabilities1 = new DesiredCapabilities();
			capabilities1.setCapability(MobileCapabilityType.UDID, iosDevice1.get(MobileCapabilityType.UDID));
			capabilities1.setCapability(MobileCapabilityType.DEVICE_NAME,iosDevice1.get(MobileCapabilityType.DEVICE_NAME));
			capabilities1.setCapability(MobileCapabilityType.PLATFORM_NAME,iosDevice1.get(MobileCapabilityType.PLATFORM_NAME));
			capabilities1.setCapability(MobileCapabilityType.PLATFORM_VERSION, iosDevice1.get(MobileCapabilityType.PLATFORM_VERSION));
			capabilities1.setCapability(IOSMobileCapabilityType.BUNDLE_ID, "im.vector.app");
			//capabilities.setCapability(MobileCapabilityType.APP,"/Users/matrix/Documents/apps/ipa/Vector-d5ce6ff019a3e6b06a20bcc849ab57074e31e773-build1399.ipa");
			//XCUITest is used because Appium Ios driver doesn't support xcode version 8.0
			capabilities1.setCapability(MobileCapabilityType.AUTOMATION_NAME,iosDevice1.get(MobileCapabilityType.AUTOMATION_NAME));
			capabilities1.setCapability(MobileCapabilityType.NO_RESET, true);
			capabilities1.setCapability(MobileCapabilityType.FULL_RESET, false);
			capabilities1.setCapability("xcodeOrgId", ReadConfigFile.getInstance().getConfMap().get("development_team"));
			capabilities1.setCapability("xcodeSigningId", ReadConfigFile.getInstance().getConfMap().get("code_sign_identity"));
			capabilities1.setCapability(IOSMobileCapabilityType.AUTO_DISMISS_ALERTS, false);
			capabilities1.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);

			appiumFactory.setiOSDriver1(new URL(Constant.getServer1HttpAddress()), capabilities1);
			System.out.println("Application "+Constant.APPLICATION_NAME+" started on IOS device "+capabilities1.getCapability(MobileCapabilityType.DEVICE_NAME) +" with DRIVER 1.");
		}

		//Create ios driver 2 if necessary
		if(appiumFactory.getiOsDriver2()==null || appiumFactory.getiOsDriver2().getSessionId()==null){
			DesiredCapabilities capabilities2 = new DesiredCapabilities();
			Map<String, String> iosDevice2=ReadConfigFile.getInstance().getDevicesMap().get("iosdevice2");
			capabilities2.setCapability(MobileCapabilityType.UDID, iosDevice2.get(MobileCapabilityType.UDID));
			capabilities2.setCapability(MobileCapabilityType.DEVICE_NAME,iosDevice2.get(MobileCapabilityType.DEVICE_NAME));
			capabilities2.setCapability(MobileCapabilityType.PLATFORM_NAME,iosDevice2.get(MobileCapabilityType.PLATFORM_NAME));
			capabilities2.setCapability(MobileCapabilityType.PLATFORM_VERSION, iosDevice2.get(MobileCapabilityType.PLATFORM_VERSION));
			capabilities2.setCapability(IOSMobileCapabilityType.BUNDLE_ID, "im.vector.app");//app
			//capabilities.setCapability(MobileCapabilityType.APP,"/Users/matrix/Documents/apps/ipa/Vector-d5ce6ff019a3e6b06a20bcc849ab57074e31e773-build1399.ipa");
			//XCUITest is used because Appium Ios driver doesn't support xcode version 8.0
			capabilities2.setCapability(MobileCapabilityType.AUTOMATION_NAME,iosDevice2.get(MobileCapabilityType.AUTOMATION_NAME));
			capabilities2.setCapability("realDeviceLogger", "/usr/local/lib/node_modules/deviceconsole/deviceconsole");
			capabilities2.setCapability(MobileCapabilityType.NO_RESET, true);
			//capabilities2.setCapability(MobileCapabilityType.FULL_RESET, false);
			capabilities2.setCapability("xcodeOrgId", ReadConfigFile.getInstance().getConfMap().get("development_team"));
			capabilities2.setCapability("xcodeSigningId", ReadConfigFile.getInstance().getConfMap().get("code_sign_identity"));
			capabilities2.setCapability("autoDismissAlerts", false);
			capabilities2.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 1200);
			
			if(!iosDriver1NeedToStart){
				Thread.sleep(5000);
				int timeWaited=0;
				int maxToWait=6;
				while (!AppiumServerStartAndStopService.service2.isRunning()&&timeWaited<maxToWait) {
					timeWaited++;
					Thread.sleep(1000);
				}
				System.out.println(timeWaited);
			}
			appiumFactory.setiOSDriver2(new URL(Constant.getServer2HttpAddress()), capabilities2);
			System.out.println("Application "+Constant.APPLICATION_NAME+" started on IOS device "+capabilities2.getCapability(MobileCapabilityType.DEVICE_NAME) +" with DRIVER 2.");
		}		
	}

	//	@AfterGroups(groups="1driver_ios")
	//	public void tearDownIosDriver1() throws Exception{
	//		appiumFactory.getiOsDriver1().quit();
	//		System.out.println("Ios DRIVER 1 quitted on IOS device "+ReadConfigFile.getInstance().getDevicesMap().get("iosdevice1").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");
	//
	//		//Stop appium server1.
	//		stopAppiumServer1();
	//	}
	//
	//	@AfterGroups(groups={"2drivers_ios"}, alwaysRun=true)
	//	public void tearDown2IosDrivers() throws Exception{
	//		appiumFactory.getiOsDriver1().quit();
	//		System.out.println("Ios DRIVER 1 quitted on IOS device "+ReadConfigFile.getInstance().getDevicesMap().get("iosdevice1").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");
	//		appiumFactory.getiOsDriver2().quit();
	//		System.out.println("Ios DRIVER 2 quitted on IOS device "+ReadConfigFile.getInstance().getDevicesMap().get("iosdevice2").get("deviceName") +", closing application "+Constant.APPLICATION_NAME+".");
	//
	//		//Stop the two appium's servers.
	//		stop2AppiumServers();
	//	}


	/**
	 * According to the chosen starting mode, start the first appium server if needed.
	 * @throws Exception 
	 */
	protected void startAppiumServer1() throws Exception{
		switch (ReadConfigFile.getInstance().getConfMap().get("starting_server_mode")) {
		case "1":
			AppiumServerStartAndStopCmdLine.startAppiumServer1IfNecessary();
			break;
		case "2":
			AppiumServerStartAndStopService.startAppiumServer1IfNecessary();
			break;
		default:
			break;
		}
	}
	/**
	 * According to the chosen starting mode, start the two appiums servers if needed.
	 * @throws Exception 
	 */
	protected void start2AppiumServers() throws Exception{
		switch (ReadConfigFile.getInstance().getConfMap().get("starting_server_mode")) {
		case "1":
			AppiumServerStartAndStopCmdLine.startAppiumServer1IfNecessary();
			AppiumServerStartAndStopCmdLine.startAppiumServer2IfNecessary();
			break;
		case "2":
			AppiumServerStartAndStopService.startAppiumServer1IfNecessary();
			AppiumServerStartAndStopService.startAppiumServer2IfNecessary();
			break;
		default:
			break;
		}
	}
	/**
	 * According to the chosen starting mode, stop the first appium.
	 * @throws Exception 
	 */
	@SuppressWarnings("unused")
	private void stopAppiumServer1() throws Exception{
		switch (ReadConfigFile.getInstance().getConfMap().get("starting_server_mode")) {
		case "1":
			AppiumServerStartAndStopCmdLine.stopAppiumServer1();
			break;
		case "2":
			AppiumServerStartAndStopService.appiumServer1Stop();
			break;
		default:
			break;
		}
	}
	/**
	 * According to the chosen starting mode, stop the two appiums servers.
	 * @throws Exception 
	 */
	private void stop2AppiumServers() throws Exception{
		switch (ReadConfigFile.getInstance().getConfMap().get("starting_server_mode")) {
		case "1":
			AppiumServerStartAndStopCmdLine.stopAppiumServer1();
			AppiumServerStartAndStopCmdLine.stopAppiumServer2();
			break;
		case "2":
			AppiumServerStartAndStopService.appiumServer1Stop();
			AppiumServerStartAndStopService.appiumServer2Stop();
			break;
		default:
			break;
		}
	}

} public class ScreenshotUtility implements ITestListener {
	public static AppiumFactory appiumFactory=AppiumFactory.getInstance();
	
	public void onTestStart(ITestResult result) {

	}

	public void onTestSuccess(ITestResult result) {
		if(appiumFactory.getCurrentDriver()!=null)captureScreenShot(result, "pass");
	}

	public void onTestFailure(ITestResult result) {
		if(appiumFactory.getCurrentDriver()!=null)captureScreenShot(result, "fail");
	}

	public void onTestSkipped(ITestResult result) {

	}

	public void onTestFailedButWithinSuccessPercentage(ITestResult result) {

	}

	public void onStart(ITestContext context) {

	}

	public void onFinish(ITestContext context) {

	}
	// Function to capture screenshot.
	public void captureScreenShot(ITestResult result, String status) {
		//choice of output screenshot according to the sut
		String os="";
		if(appiumFactory.getCurrentDriver() instanceof AndroidDriver<?>){
			os="android";
		}else{
			os="ios";
		}
		System.out.println("Screenshot taken on "+os);
		String destDir = "";
		String passfailMethod = result.getMethod().getRealClass().getSimpleName() + "." + result.getMethod().getMethodName();
		// To capture screenshot.
		File scrFile = ((TakesScreenshot) appiumFactory.getCurrentDriver()).getScreenshotAs(OutputType.FILE);
		DateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy__hh_mm_ssaa");

		// If status = fail then set folder name "screenshots/Failures"
		if (status.equalsIgnoreCase("fail")) {
			destDir = "screenshots_"+os+"/Failures";
		}
		// If status = pass then set folder name "screenshots/Success"
		else if (status.equalsIgnoreCase("pass")) {
			destDir = "screenshots_"+os+"/Success";
		}

		// To create folder to store screenshots
		new File(destDir).mkdirs();
		// Set file name with combination of test class name + date time.
		String destFile = passfailMethod + " - " + dateFormat.format(new Date()) + ".png";

		try {
			// Store file at destination folder location
			FileUtils.copyFile(scrFile, new File(destDir + "/" + destFile));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
import java.lang.reflect.Method;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import pom_android.RiotUnknownDevicesPageObjects;
import pom_ios.RiotCallingPageObjects;
import pom_ios.RiotIncomingCallPageObjects;
import pom_ios.RiotRoomDetailsPageObjects;
import pom_ios.RiotRoomPageObjects;
import pom_ios.RiotUnknownDevicesListPageObjects;
import pom_ios.RiotUnknownDevicesModalPageObjects;
import pom_ios.RiotVerifyDevicePageObjects;
import pom_ios.main_tabs.RiotHomePageTabObjects;
import utility.Constant;
import utility.RiotParentTest;
import utility.ScreenshotUtility;
package mobilestests_ios;




/**
 * Tests on e2e encryption on IOS platform.
 * @author matrix
 *
 */
@Listeners({ ScreenshotUtility.class })
public class RiotE2eEncryptionTests_ios extends RiotParentTest{
	private String roomWithEncryption="auto test encryption";
	private String oneToOneRoomWithEncryption="1:1e2e_automated tests";
	private String encrypted_msg_1="msg sent in encrypted room";
	private String encrypted_msg_2="this msg will be decrypted";
	private String participant1DisplayName="riotuser9";
	private String participant2DisplayName="riotuser10";	


	/**
	 * 1. Create a room and enable encryption. </br>
	 * 2. Send a photo </br>
	 * Check that the photo is correctly uploaded.  </br>
	 * @throws InterruptedException 
	 */
	@Test(groups={"1driver_ios"}, description="upload a photo in encrypted room")
	public void sendPhotoInEncryptedRoom() throws InterruptedException{
		//1. Create room with Device 1 and enable encryption.
		RiotHomePageTabObjects hpA = new RiotHomePageTabObjects(appiumFactory.getiOsDriver1());
		RiotRoomPageObjects roomPage= hpA.createRoom();
		
		RiotRoomDetailsPageObjects roomDetails =roomPage.openDetailView();
		roomDetails.settingsTab.click();
		scrollToBottom(appiumFactory.getiOsDriver1());
		roomDetails.enableEncryption();
		roomDetails.roomDetailsDoneButton.click();
		roomDetails.waitUntilDetailsDone();

		//2. Send a photo
		roomPage.attachPhotoFromCamera("Small");
		//verifies that it's displayed in the message list
		roomPage.waitAndCheckForMediaToBeUploaded(roomPage.getLastBubble(), 15);
		//TODO check size of the uploaded photo
		//org.openqa.selenium.Dimension takenPhoto=newRoomDevice1.getAttachedImageByPost(newRoomDevice1.getLastPost()).getSize();
		//Assert.assertTrue(takenPhoto.height!=0 && takenPhoto.width!=0, "The unsent photo has null dimension");
		//roomPage.menuBackButton.click();
	}
	/**
	 * 1. Create room with Device 1 and enable encryption. </br>
	 * Check that the last event in the room is about turning e2e encryption </br>
	 * 2. Sent a message. </br>
	 * 3. Send invitation to user on Device 2 and device 2 accepts. </br>
	 * Check that user on Device 2 can't read the msg sent by Device 1 before he joined. </br>
	 * 4. Send a message with device 2 </br>
	 * Check that user on device 1 can decrypt and read the message.
	 * @throws InterruptedException 
	 */
	@Test(groups={"2drivers_ios"})
	public void tryReadEncryptedMessageSentAfterJoining() throws InterruptedException{
		//1. Create room with Device 1 and enable encryption.
		RiotHomePageTabObjects homePage1 = new RiotHomePageTabObjects(appiumFactory.getiOsDriver1());
		RiotRoomPageObjects roomPage1= homePage1.createRoom();
		roomPage1.roomMembersDetailIcon.click();
		RiotRoomDetailsPageObjects roomDetails = new RiotRoomDetailsPageObjects(appiumFactory.getiOsDriver1());
		roomDetails.settingsTab.click();
		roomDetails.changeRoomName(roomWithEncryption);
		scrollToBottom(appiumFactory.getiOsDriver1());
		roomDetails.enableEncryption();
		roomDetails.roomDetailsDoneButton.click();
		roomDetails.waitUntilDetailsDone();
		RiotHomePageTabObjects homePage2 = new RiotHomePageTabObjects(appiumFactory.getiOsDriver2());

		//2. Send a message.
		roomPage1.sendAMessage(encrypted_msg_1);
		Assert.assertTrue(roomPage1.getTextViewFromBubble(roomPage1.getLastBubble()).getText().contains(encrypted_msg_1), "Msg sent in e2e room isn't received in sender's room");

		//3. Send invitation to user on Device 2 and device 2 accepts.
		roomPage1.openRoomDetails.click();
		RiotRoomDetailsPageObjects roomDetails1=new RiotRoomDetailsPageObjects(appiumFactory.getiOsDriver1());
		roomDetails1.addParticipant(getMatrixIdFromDisplayName(participant2DisplayName));
		roomDetails1.menuBackButton.click();
		//accept invitation with device 2
		homePage2.previewInvitation(roomWithEncryption);
		RiotRoomPageObjects roomPage2 = new RiotRoomPageObjects(appiumFactory.getiOsDriver2());
		roomPage2.joinRoomButton.click();
		roomPage2.closeWarningAlertAboutBetaStateOfE2e();

		//Check that user on Device 2 can't read the msg sent by Device 1 before he joined.
		roomPage2.waitForBubblesToBeDisplayed();
		int index=roomPage2.bubblesList.size()-2;
		Assert.assertTrue(roomPage2.getTextViewFromBubble(roomPage2.getBubbleByIndex(index)).getText().contains(utility.Constant.ENCRYPTION_UNKNOWN_SESSION_ID_MSG), "Msg sent by device 1 isn't encrypted, or encrypted unknown msg has changed");