Skip to content
This repository has been archived by the owner on Apr 4, 2022. It is now read-only.

WIP: #239 #248

Closed
wants to merge 14 commits into from
24 changes: 20 additions & 4 deletions src/app/inbox/inbox-compose/inbox-compose.component.html
Expand Up @@ -7,6 +7,22 @@
<div>
<h4>Compose <span class="fw-semi-bold">New</span></h4>
<div class="compose-form" id="compose-view">
<!-- Show Balance Label -->
<div class="form-group row mb-0">
<div class="col-md-10 col-lg-9 offset-md-2 offset-sm-0 ">
<b class="float-right ">Balance: <label for="balance">
{{balance}} {{currency}}</label></b>
</div>
</div>
<br />
<!-- ./Show Balance Label -->
<!-- Show Fees Label -->
<!-- <div class="form-group row mb-0">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please can you remove this until it's implemented?

<div class="col-md-10 col-lg-9 offset-md-2 offset-sm-0">
<b class="float-right col-sm-3 col-md-3 col-lg-3">Fees:<label for="fee"> 0.00008 Eth </label></b>
</div>
</div> -->
<!-- ./Show Fees Label -->

<form #mailForm="ngForm" id="message-compose" (ngSubmit)="onSubmit()" autocomplete="off">

Expand All @@ -20,8 +36,9 @@ <h4>Compose <span class="fw-semi-bold">New</span></h4>
<img class="rounded-circle addressIcon" src={{generateIdenticon(model.from)}} alt="">
</div>
</div>

<select class="form-control" [(ngModel)]="model.from" name="from" [disabled]="isReply">

<select class="form-control" [(ngModel)]="model.from" name="from" [disabled]="isReply"
(change)="updateBalanceForAddress($event.target.value)">
<option *ngFor="let address of fromAddresses; let i = index" [value]="address">
{{address}}
</option>
Expand All @@ -44,8 +61,7 @@ <h4>Compose <span class="fw-semi-bold">New</span></h4>
</div>
</div>
<input type="text" id="messageTo" placeholder="To" name="to" class="form-control "
placeholder="e.g. 0x0000...0000 or mailchain.eth" [(ngModel)]="messageToField"
[disabled]="isReply"
placeholder="e.g. 0x0000...0000 or mailchain.eth" [(ngModel)]="messageToField" [disabled]="isReply"
(keyup)="recipientResolve($event)">
</div>
</div>
Expand Down
43 changes: 34 additions & 9 deletions src/app/inbox/inbox-compose/inbox-compose.component.spec.ts
Expand Up @@ -25,6 +25,8 @@ import { EnvelopeServiceStub } from 'src/app/services/mailchain/envelope/envelop
import { PublicKeyServiceStub } from 'src/app/services/mailchain/public-key/public-key.service.stub';
import { SendServiceStub } from 'src/app/services/mailchain/messages/send.service.stub';
import { NameserviceServiceStub } from 'src/app/services/mailchain/nameservice/nameservice.service.stub';
import { BalanceService } from 'src/app/services/mailchain/addresses/balance.service';
import { BalanceServiceStub } from 'src/app/services/mailchain/addresses/balance.service.stub';


// Workaround:
Expand All @@ -47,6 +49,8 @@ describe('InboxComposeComponent', () => {

const currentAccount = '0x92d8f10248c6a3953cc3692a894655ad05d61efb';
const currentAccount2 = '0x0123456789012345678901234567890123456789';
const balance = 0;
const fees = '';
const ensName = 'mailchain.eth';
const addresses = [currentAccount, currentAccount2];

Expand All @@ -65,6 +69,7 @@ describe('InboxComposeComponent', () => {
{ provide: PublicKeyService, useClass: PublicKeyServiceStub },
{ provide: SendService, useClass: SendServiceStub },
{ provide: NameserviceService, useClass: NameserviceServiceStub },
{ provide: BalanceService, useClass: BalanceServiceStub },

],
imports: [
Expand Down Expand Up @@ -145,6 +150,24 @@ describe('InboxComposeComponent', () => {
expect(component.model.body).toBe('')
})


describe('handling the balance', () => {
it('should initialize a balance in the "balance" field using an available balance', async () => {
await component.ngOnInit();
fixture.detectChanges()
expect(component.balance).toBe(balance)
})
});

describe('handling the fees', () => {
it('should initialize a Fees in the "fees" field', async () => {
await component.ngOnInit();
fixture.detectChanges()
expect(component.fees).toBe(fees)
})
});


describe('handling the envelope', () => {
it('should initialize an envelope in the "envelope" field using an available envelop', async () => {
envelopes = mailchainTestService.envelopeTypeMli()
Expand Down Expand Up @@ -177,7 +200,7 @@ describe('InboxComposeComponent', () => {
// TODO
await component.ngOnInit();
// expect(component.mailForm).toBe('0x0123456789abcdef0123456789abcdef01234567')
})
})

it('should initialize the model "replyTo" field with the sender address', async () => {
await component.ngOnInit();
Expand All @@ -187,27 +210,27 @@ describe('InboxComposeComponent', () => {
it('should initialize the model "to" field with the reply-to recipient address', async () => {
await component.ngOnInit();
expect(component.model.to).toBe('0xABCDEABCDE012345678901234567890123456789')
})
})

xit('should disable the model "to" field on page so the address cannot be changed', async () => {
// TODO
await component.ngOnInit();
// expect(component.mailForm).toBe('0xABCDEABCDE012345678901234567890123456789')
})
})

it('should initialize the model "subject" field with the original message field + a prefix of "Re: "', async () => {
await component.ngOnInit();
expect(component.model.subject).toBe('Re: Mailchain Test!')
})


it('should not re-initialize the model "subject" field with an extra prefix of "Re: "', async () => {
component.currentMessage.subject = "Re: Mailchain Test!"
await component.ngOnInit();
expect(component.model.subject).toBe('Re: Mailchain Test!')
})





Expand All @@ -233,7 +256,7 @@ describe('InboxComposeComponent', () => {
component.currentMessage.headers["content-type"] = "text/html; charset=\"UTF-8\""
})


it('should initialize the model "body" field with the original message field and wrap the body in a `blockquote`', async () => {
let response = "<p></p><p><strong>From:</strong> <0x0123456789012345678901234567890123456789@testnet.ethereum><br><strong>Reply To:</strong> <0xABCDEABCDE012345678901234567890123456789@testnet.ethereum><br><strong>Date:</strong> 2019-06-07T14:53:36Z<br><strong>To:</strong> <0x0123456789abcdef0123456789abcdef01234567@testnet.ethereum><br><strong>Subject:</strong> Mailchain Test!</p><blockquote>A body<br></blockquote>"

Expand Down Expand Up @@ -386,7 +409,7 @@ describe('InboxComposeComponent', () => {
component.evaluateReply()
expect(component.isReply).toBeTrue()
})

})

describe('setupRecipientAddressLookupSubscription', () => {
Expand Down Expand Up @@ -667,3 +690,5 @@ describe('InboxComposeComponent', () => {
});

});


46 changes: 41 additions & 5 deletions src/app/inbox/inbox-compose/inbox-compose.component.ts
Expand Up @@ -7,6 +7,8 @@ import { PublicKeyService } from 'src/app/services/mailchain/public-key/public-k
import { AddressesService } from 'src/app/services/mailchain/addresses/addresses.service';
import { EnvelopeService } from 'src/app/services/mailchain/envelope/envelope.service';
import { NameserviceService } from 'src/app/services/mailchain/nameservice/nameservice.service';
import { BalanceService } from 'src/app/services/mailchain/addresses/balance.service';
tboeckmann marked this conversation as resolved.
Show resolved Hide resolved

import { Subject, of, Observable } from 'rxjs';

import { debounceTime, distinctUntilChanged, mergeMap } from "rxjs/operators";
Expand All @@ -15,6 +17,7 @@ import { ModalConnectivityErrorComponent } from 'src/app/modals/modal-connectivi

import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { CKEditorComponent } from '@ckeditor/ckeditor5-angular';
import { getCurrencySymbol } from '@angular/common';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this used?


@Component({
selector: '[inbox-compose]',
Expand All @@ -34,6 +37,9 @@ export class InboxComposeComponent implements OnInit {
public model = new Mail()
public fromAddresses: Array<any> = []
public envelopes: Array<any> = []
public balance: number = 0
public currency: string = ""
public fees: string = ""

public sendMessagesDisabled: boolean = false;
private subscription
Expand Down Expand Up @@ -64,6 +70,7 @@ export class InboxComposeComponent implements OnInit {
private addressesService: AddressesService,
private envelopeService: EnvelopeService,
private nameserviceService: NameserviceService,
private balanceService: BalanceService,
private modalService: BsModalService,
) {
this.initMail()
Expand All @@ -78,6 +85,7 @@ export class InboxComposeComponent implements OnInit {
this.model.replyTo = ""
this.model.subject = ""
this.model.body = ""

}

/**
Expand Down Expand Up @@ -120,6 +128,32 @@ export class InboxComposeComponent implements OnInit {
this.envelopes = await this.envelopeService.getEnvelope();
}


/**
* updates the balance whenver address dropdwon value is changed
*/

public async updateBalanceForAddress(address) {
this.balance = await this.balanceService.getBalance(address, this.currentProtocol, this.currentNetwork);

}

private async setBalance() {
if (this.currentAccount != undefined) {

this.balance = await this.balanceService.getBalance(this.currentAccount, this.currentProtocol, this.currentNetwork);
}
}

/**
* Sets the currency
*/
private async setCurrency() {
this.currency = await this.mailchainService.getCurrencyForProtocol(this.currentProtocol)
}



/**
* Returns the identicon for the an address
* @param address the address
Expand Down Expand Up @@ -197,7 +231,7 @@ export class InboxComposeComponent implements OnInit {
mergeMap(searchVal => {
return this.resolveAddress(searchVal)
})
).subscribe((res) => {
).subscribe((res) => {
res.subscribe(val => {
let address = val['body']['address']
if (
Expand Down Expand Up @@ -353,7 +387,9 @@ export class InboxComposeComponent implements OnInit {
this.evaluateReply()
this.handleReplyFields()
this.setupRecipientAddressLookupSubscription()
}
await this.setBalance()
await this.setCurrency()
}

/**
* Handles content-type in the view
Expand Down Expand Up @@ -463,21 +499,21 @@ export class InboxComposeComponent implements OnInit {
*/
private handleReplyFields() {
if (this.currentMessage && this.currentMessage.headers) {

if (this.inputContentType == "html") {
this.handleReplyInHtml()
} else if (this.inputContentType == "plaintext") {
this.handleReplyInPlaintext()
}

if (this.currentMessage.headers["reply-to"] && this.currentMessage.headers["reply-to"].length) {
this.model.to = this.mailchainService.parseAddressFromMailchain(this.currentProtocol, this.currentMessage.headers["reply-to"])
} else {
this.model.to = this.mailchainService.parseAddressFromMailchain(this.currentProtocol, this.currentMessage.headers["from"])
}

this.messageToField = this.currentRecipientValue = this.model.to

this.model.replyTo = this.model.from = this.mailchainService.parseAddressFromMailchain(this.currentProtocol, this.currentMessage.headers.to)
this.model.subject = this.addRePrefixToSubject(this.currentMessage["subject"])
}
Expand Down
72 changes: 72 additions & 0 deletions src/app/services/mailchain/addresses/balance.service.spec.ts
@@ -0,0 +1,72 @@
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { BalanceService } from './balance.service';
import { MailchainTestService } from 'src/app/test/test-helpers/mailchain-test.service';
import { HttpHelpersService } from '../../helpers/http-helpers/http-helpers.service';
import { ProtocolsServiceStub } from '../protocols/protocols.service.stub';
import { ProtocolsService } from '../protocols/protocols.service';
import { Observable, of } from 'rxjs';


describe('BalanceService', () => {

let balanceService: BalanceService;
let httpTestingController: HttpTestingController;
let mailchainTestService: MailchainTestService
let serverResponse

const currentAccount = '0x92d8f10248c6a3953cc3692a894655ad05d61efb';
const desiredUrl = `http://127.0.0.1:8080/api/addresses/` + currentAccount + `/balance?protocol=ethereum&network=mainnet`

beforeEach(() => {
TestBed.configureTestingModule({
providers: [
HttpHelpersService,
{ provide: ProtocolsService, useClass: ProtocolsServiceStub },
BalanceService,
],
imports: [HttpClientTestingModule]
});

balanceService = TestBed.inject(BalanceService);
mailchainTestService = TestBed.inject(MailchainTestService);
httpTestingController = TestBed.inject(HttpTestingController);

//serverResponse = mailchainTestService.senderAddressesEthereumObserveResponse()
// expectedAddresses = mailchainTestService.senderAddresses()
});

afterEach(() => {
httpTestingController.verify();
});


describe('initUrl', () => {
it('should initialize the url', () => {
balanceService.initUrl()
expect(balanceService['url']).toEqual('http://127.0.0.1:8080/api')
});
})

it('should be created', () => {
expect(balanceService).toBeTruthy();
});

describe('getBalance', () => {
beforeEach(() => {
let obs: Observable<any> = of(mailchainTestService.senderBalanceEthereumObserveResponse())
tboeckmann marked this conversation as resolved.
Show resolved Hide resolved
spyOn(balanceService, 'getBalance').and.returnValue(
obs.toPromise()
)
});
it('should get balance for addresses', async () => {
let result
await balanceService.getBalance(currentAccount, 'ethereum', 'mainnet').then(res => {
result = res
});
expect(result).toEqual(mailchainTestService.senderBalanceEthereumObserveResponse())
expect(balanceService.getBalance).toHaveBeenCalled()
});
})
});