src/test/java/com/hdekker/moondumpui/SubscriptionLinkTests.java
@Test
	public void itCanUnsubscribe() throws InterruptedException {
		
		// STUB data in DB for test
		
		// stores un-subscribe key to user
		DynamoDbAsyncClient client = DynamoDbAsyncClient.builder()
				.region(Region.of(db.getRegion()))
				.build();
	
		// add temp test subscription
		IndicatorSubscription uss = new IndicatorSubscription(
				"test-asset-unsubscribe", 
				"unsubunittest@testemail.com", 
				Map.of("ind", Map.of("prop1", 0.34)), 
				"testIndicatorSubscriptionLinkTests", 
				List.of("ind"), 
				"test-interface", List.of(34.00));
		
		Map<String, AttributeValue> attr = Marshalling.converter()
				.apply(uss);
		
		HashMap<String, AttributeValue> withKeys = new HashMap<>(attr);
		withKeys.put(db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_SUBSCRIPTION.getPrimaryKeyValue())
						.build());
		withKeys.put(db.getSortKey(),
					AttributeValue.builder()
						.s(Marshalling.createSortKey().apply(uss))
						.build());
		
		// add test subscription
		CompletableFuture<PutItemResponse> tempSubscriptionAddFuture = client.putItem(b->{
			
			b.tableName(db.getTableName());
			b.item(withKeys);
			
		});
		
		assertThat(tempSubscriptionAddFuture.join().sdkHttpResponse().statusCode(), Matchers.equalTo(200));
		
		// at this point UI flow should have added an unsubscribe key for email.
		String sha = DigestUtils.sha256Hex(db.getAppAdminEmail());
		
		client.putItem(p->{
			
			p.tableName(db.getTableName());
			p.item(Map.of(
					db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_UNSUBSCRIBE.getPrimaryKeyValue())
						.build(),
					db.getSortKey(),
					AttributeValue.builder()
						.s(sha)
						.build(),
					"email",
					AttributeValue.builder()
						.s("unsubunittest@testemail.com")
						.build()
					
			));
		}).join();
		
		// check that sha can be queried by email
		// so that the core service can create 
		// the subscription link when sending
		QueryResponse shaByEmailLookup = client.query(b->{
			b.tableName(db.getTableName());
			b.indexName("email-index");
			b.expressionAttributeValues(Map.of(
					":" + db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_UNSUBSCRIBE.getPrimaryKeyValue())
						.build(),
					":email",
					AttributeValue.builder()
						.s("unsubunittest@testemail.com")
						.build())
			);
			b.keyConditionExpression(db.getPrimaryKey() + "= :" + db.getPrimaryKey() 
									+ " AND " + "email = :email");
			
		}).join();
		
		assertThat("An LSI should allow access by email.", shaByEmailLookup.hasItems(), Matchers.equalTo(true));
		assertThat("Should only be a single key available for a given email.", shaByEmailLookup.items().size(), Matchers.equalTo(1));
		
		// calls view with an un-subscribe key
		UI.getCurrent().navigate("unsubscribe/" + shaByEmailLookup.items().get(0).get(db.getSortKey()).s());
		
		// need to allow view to access database
		Thread.sleep(4000);
		
		// get a subscription
		Unsubscribe unsubClass = LocatorJ._get(Unsubscribe.class);
		
		List<IndicatorSubscription> usss = unsubClass.getUserSubscriptions();
		assertThat("View should have only found a single subscription for unsubunittest@testemail.com.", usss.size(), Matchers.equalTo(1));
		
		// mocks user interaction - remove subscription
		isr.deleteSubscription(usss.get(0));
		esr.deleteEmailSHA(sha);
		
		Thread.sleep(2000); // let view do it thing.
		
		// checks
		GetItemResponse shaRef = client.getItem(b->{
			
			b.tableName(db.getTableName());
			b.key(Map.of(
					db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_UNSUBSCRIBE.getPrimaryKeyValue())
						.build(),
					db.getSortKey(),
					AttributeValue.builder()
						.s(sha)
						.build()
					
			));
		}).join();
		
		assertThat("As no more subscriptions exist, the sha reference should be removed.", shaRef.hasItem(), Matchers.equalTo(false));
		
		GetItemResponse subRef = client.getItem(b->{
			
			b.tableName(db.getTableName());
			b.key(Map.of(
					db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_SUBSCRIPTION.getPrimaryKeyValue())
						.build(),
					db.getSortKey(),
					AttributeValue.builder()
						.s(Marshalling.createSortKey().apply(uss))
						.build()
					
			));
		}).join();
		
		assertThat("The subscription must be removed when unsubscribe is called.", subRef.hasItem(), Matchers.equalTo(false));
		
	}
/**
	 *  This test should not invoke and email
	 * @throws InterruptedException 
	 * 
	 */
This test should not invoke and email
@throws InterruptedException
This test should not invoke and email @throws InterruptedException
@Test
	public void itCanUnsubscribe() throws InterruptedException {
		DynamoDbAsyncClient client = DynamoDbAsyncClient.builder()
				.region(Region.of(db.getRegion()))
				.build();
		IndicatorSubscription uss = new IndicatorSubscription(
				"test-asset-unsubscribe", 
				"unsubunittest@testemail.com", 
				Map.of("ind", Map.of("prop1", 0.34)), 
				"testIndicatorSubscriptionLinkTests", 
				List.of("ind"), 
				"test-interface", List.of(34.00));
		Map<String, AttributeValue> attr = Marshalling.converter()
				.apply(uss);
		HashMap<String, AttributeValue> withKeys = new HashMap<>(attr);
		withKeys.put(db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_SUBSCRIPTION.getPrimaryKeyValue())
						.build());
		withKeys.put(db.getSortKey(),
					AttributeValue.builder()
						.s(Marshalling.createSortKey().apply(uss))
						.build());
		CompletableFuture<PutItemResponse> tempSubscriptionAddFuture = client.putItem(b->{
			b.tableName(db.getTableName());
			b.item(withKeys);
		});
		assertThat(tempSubscriptionAddFuture.join().sdkHttpResponse().statusCode(), Matchers.equalTo(200));
		String sha = DigestUtils.sha256Hex(db.getAppAdminEmail());
		client.putItem(p->{
			p.tableName(db.getTableName());
			p.item(Map.of(
					db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_UNSUBSCRIBE.getPrimaryKeyValue())
						.build(),
					db.getSortKey(),
					AttributeValue.builder()
						.s(sha)
						.build(),
					"email",
					AttributeValue.builder()
						.s("unsubunittest@testemail.com")
						.build()
			));
		}).join();
		QueryResponse shaByEmailLookup = client.query(b->{
			b.tableName(db.getTableName());
			b.indexName("email-index");
			b.expressionAttributeValues(Map.of(
					":" + db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_UNSUBSCRIBE.getPrimaryKeyValue())
						.build(),
					":email",
					AttributeValue.builder()
						.s("unsubunittest@testemail.com")
						.build())
			);
			b.keyConditionExpression(db.getPrimaryKey() + "= :" + db.getPrimaryKey() 
									+ " AND " + "email = :email");
		}).join();
		assertThat("An LSI should allow access by email.", shaByEmailLookup.hasItems(), Matchers.equalTo(true));
		assertThat("Should only be a single key available for a given email.", shaByEmailLookup.items().size(), Matchers.equalTo(1));
		UI.getCurrent().navigate("unsubscribe/" + shaByEmailLookup.items().get(0).get(db.getSortKey()).s());
		Thread.sleep(4000);
		Unsubscribe unsubClass = LocatorJ._get(Unsubscribe.class);
		List<IndicatorSubscription> usss = unsubClass.getUserSubscriptions();
		assertThat("View should have only found a single subscription for unsubunittest@testemail.com.", usss.size(), Matchers.equalTo(1));
		isr.deleteSubscription(usss.get(0));
		esr.deleteEmailSHA(sha);
		Thread.sleep(2000); 
		GetItemResponse shaRef = client.getItem(b->{
			b.tableName(db.getTableName());
			b.key(Map.of(
					db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_UNSUBSCRIBE.getPrimaryKeyValue())
						.build(),
					db.getSortKey(),
					AttributeValue.builder()
						.s(sha)
						.build()
			));
		}).join();
		assertThat("As no more subscriptions exist, the sha reference should be removed.", shaRef.hasItem(), Matchers.equalTo(false));
		GetItemResponse subRef = client.getItem(b->{
			b.tableName(db.getTableName());
			b.key(Map.of(
					db.getPrimaryKey(),
					AttributeValue.builder()
						.s(PrimaryKeySpec.INDICATOR_SUBSCRIPTION.getPrimaryKeyValue())
						.build(),
					db.getSortKey(),
					AttributeValue.builder()
						.s(Marshalling.createSortKey().apply(uss))
						.build()
			));
		}).join();
		assertThat("The subscription must be removed when unsubscribe is called.", subRef.hasItem(), Matchers.equalTo(false));
	}
@ Test public void itCanUnsubscribe ( ) throws InterruptedException { DynamoDbAsyncClient client = DynamoDbAsyncClient . builder ( ) . region ( Region . of ( db . getRegion ( ) ) ) . build ( ) ; IndicatorSubscription uss = new IndicatorSubscription ( "test-asset-unsubscribe" , "unsubunittest@testemail.com" , Map . of ( "ind" , Map . of ( "prop1" , 0.34 ) ) , "testIndicatorSubscriptionLinkTests" , List . of ( "ind" ) , "test-interface" , List . of ( 34.00 ) ) ; Map < String , AttributeValue > attr = Marshalling . converter ( ) . apply ( uss ) ; HashMap < String , AttributeValue > withKeys = new HashMap < > ( attr ) ; withKeys . put ( db . getPrimaryKey ( ) , AttributeValue . builder ( ) . s ( PrimaryKeySpec . INDICATOR_SUBSCRIPTION . getPrimaryKeyValue ( ) ) . build ( ) ) ; withKeys . put ( db . getSortKey ( ) , AttributeValue . builder ( ) . s ( Marshalling . createSortKey ( ) . apply ( uss ) ) . build ( ) ) ; CompletableFuture < PutItemResponse > tempSubscriptionAddFuture = client . putItem ( b -> { b . tableName ( db . getTableName ( ) ) ; b . item ( withKeys ) ; } ) ; assertThat ( tempSubscriptionAddFuture . join ( ) . sdkHttpResponse ( ) . statusCode ( ) , Matchers . equalTo ( 200 ) ) ; String sha = DigestUtils . sha256Hex ( db . getAppAdminEmail ( ) ) ; client . putItem ( p -> { p . tableName ( db . getTableName ( ) ) ; p . item ( Map . of ( db . getPrimaryKey ( ) , AttributeValue . builder ( ) . s ( PrimaryKeySpec . INDICATOR_UNSUBSCRIBE . getPrimaryKeyValue ( ) ) . build ( ) , db . getSortKey ( ) , AttributeValue . builder ( ) . s ( sha ) . build ( ) , "email" , AttributeValue . builder ( ) . s ( "unsubunittest@testemail.com" ) . build ( ) ) ) ; } ) . join ( ) ; QueryResponse shaByEmailLookup = client . query ( b -> { b . tableName ( db . getTableName ( ) ) ; b . indexName ( "email-index" ) ; b . expressionAttributeValues ( Map . of ( ":" + db . getPrimaryKey ( ) , AttributeValue . builder ( ) . s ( PrimaryKeySpec . INDICATOR_UNSUBSCRIBE . getPrimaryKeyValue ( ) ) . build ( ) , ":email" , AttributeValue . builder ( ) . s ( "unsubunittest@testemail.com" ) . build ( ) ) ) ; b . keyConditionExpression ( db . getPrimaryKey ( ) + "= :" + db . getPrimaryKey ( ) + " AND " + "email = :email" ) ; } ) . join ( ) ; assertThat ( "An LSI should allow access by email." , shaByEmailLookup . hasItems ( ) , Matchers . equalTo ( true ) ) ; assertThat ( "Should only be a single key available for a given email." , shaByEmailLookup . items ( ) . size ( ) , Matchers . equalTo ( 1 ) ) ; UI . getCurrent ( ) . navigate ( "unsubscribe/" + shaByEmailLookup . items ( ) . get ( 0 ) . get ( db . getSortKey ( ) ) . s ( ) ) ; Thread . sleep ( 4000 ) ; Unsubscribe unsubClass = LocatorJ . _get ( Unsubscribe . class ) ; List < IndicatorSubscription > usss = unsubClass . getUserSubscriptions ( ) ; assertThat ( "View should have only found a single subscription for unsubunittest@testemail.com." , usss . size ( ) , Matchers . equalTo ( 1 ) ) ; isr . deleteSubscription ( usss . get ( 0 ) ) ; esr . deleteEmailSHA ( sha ) ; Thread . sleep ( 2000 ) ; GetItemResponse shaRef = client . getItem ( b -> { b . tableName ( db . getTableName ( ) ) ; b . key ( Map . of ( db . getPrimaryKey ( ) , AttributeValue . builder ( ) . s ( PrimaryKeySpec . INDICATOR_UNSUBSCRIBE . getPrimaryKeyValue ( ) ) . build ( ) , db . getSortKey ( ) , AttributeValue . builder ( ) . s ( sha ) . build ( ) ) ) ; } ) . join ( ) ; assertThat ( "As no more subscriptions exist, the sha reference should be removed." , shaRef . hasItem ( ) , Matchers . equalTo ( false ) ) ; GetItemResponse subRef = client . getItem ( b -> { b . tableName ( db . getTableName ( ) ) ; b . key ( Map . of ( db . getPrimaryKey ( ) , AttributeValue . builder ( ) . s ( PrimaryKeySpec . INDICATOR_SUBSCRIPTION . getPrimaryKeyValue ( ) ) . build ( ) , db . getSortKey ( ) , AttributeValue . builder ( ) . s ( Marshalling . createSortKey ( ) . apply ( uss ) ) . build ( ) ) ) ; } ) . join ( ) ; assertThat ( "The subscription must be removed when unsubscribe is called." , subRef . hasItem ( ) , Matchers . equalTo ( false ) ) ; }
This test should not invoke and email
 @throws InterruptedException
This test should not invoke and email @throws InterruptedException
// STUB data in DB for test // stores un-subscribe key to user // add temp test subscription // add test subscription // at this point UI flow should have added an unsubscribe key for email. // check that sha can be queried by email // so that the core service can create  // the subscription link when sending // calls view with an un-subscribe key // need to allow view to access database // get a subscription // mocks user interaction - remove subscription // let view do it thing. // checks