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

Commit

Permalink
add more tests (#60)
Browse files Browse the repository at this point in the history
* remove dupe sections from readme

* Add TOC

* add documentation to README for server settings
fix naming error (url >> host)

* render message body as courier to support ascii layout

* asciify the message body

* fix problem displaying `Nothing here yet` (see issue #33)

* add ascii invoice used for testing

* add all testnets

* add/ update tests
Add mocks for inboxComponent

* add networks for spec

* Add versioning from package.json (to be semantic versioning)

* skip strange behaviour in test for now

* add coveralls status

* add coveralls

* add coveralls config

* refactor addresses endpoint into its own service

* remove unneeded import

* add protocols service

* add setNetworkList
remove getPublicNetworks method

* fix testing errors
closes #44

* add more coverage

* add some more unit tests

* add tests and document method

* add tests for address pipe
add method documentation

* require args for pipe

* add gitter badge

* add coverage: pipe tests

* remove changeActiveItem method

* inbox tests

* add test to inbox component;
refactor and review inbox component

* add tests
refactor getMails() and move methods to services

* clean up form
add tests
  • Loading branch information
tboeckmann committed Jul 24, 2019
1 parent ea3f862 commit e2d7ecb
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/app/inbox/inbox-compose/inbox-compose.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<h4>Compose <span class="fw-semi-bold">New</span></h4>
<div class="compose-form" id="compose-view">

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

<div class="form-group">
<label for="from">From:</label>
Expand Down
224 changes: 224 additions & 0 deletions src/app/inbox/inbox-compose/inbox-compose.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,44 @@ import { InboxComposeComponent } from './inbox-compose.component';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { HttpHelpersService } from 'src/app/services/helpers/http-helpers/http-helpers.service';
import { Mail } from 'src/app/models/mail';
import { AddressesService } from 'src/app/services/mailchain/addresses/addresses.service';
import { MailchainTestService } from 'src/app/test/test-helpers/mailchain-test.service';
import { of } from 'rxjs';
import { PublicKeyService } from 'src/app/services/mailchain/public-key/public-key.service';
import { RouterTestingModule } from '@angular/router/testing';
import { SendService } from 'src/app/services/mailchain/messages/send.service';
import { OutboundMail } from 'src/app/models/outbound-mail';
import { MailchainService } from 'src/app/services/mailchain/mailchain.service';

describe('InboxComposeComponent', () => {
let component: InboxComposeComponent;
let fixture: ComponentFixture<InboxComposeComponent>;
let mailchainTestService: MailchainTestService
let publicKeyService: PublicKeyService
let sendService : SendService
let mailchainService: MailchainService

const currentAccount = '0x0123456789012345678901234567890123456789';
const currentAccount2 = '0x0123456789abcdef0123456789abcdef01234567';
const addresses = [currentAccount, currentAccount2];

class AddressesServiceStub {
getAddresses(){
return addresses
}
}
class PublicKeyServiceStub {
getPublicKeyFromAddress(publicAddress, network) {
return of(['1234567890'])
}
}
class SendServiceStub {
sendMail(outboundMail: OutboundMail, network: string){
return of([])
}
}


beforeEach(async(() => {
TestBed.configureTestingModule({
Expand All @@ -16,13 +50,24 @@ describe('InboxComposeComponent', () => {
],
providers: [
HttpHelpersService,
MailchainService,
{ provide: AddressesService, useClass: AddressesServiceStub },
{ provide: PublicKeyService, useClass: PublicKeyServiceStub },
{ provide: SendService, useClass: SendServiceStub },

],
imports: [
FormsModule,
HttpClientModule,
RouterTestingModule
]
})
.compileComponents();
mailchainTestService = TestBed.get(MailchainTestService);
publicKeyService = TestBed.get(PublicKeyService);
sendService = TestBed.get(SendService);
mailchainService = TestBed.get(MailchainService);

}));

beforeEach(() => {
Expand All @@ -38,4 +83,183 @@ describe('InboxComposeComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});

describe('ngOnInit', () => {
describe('initMail', () => {

it('should start with an empty Mail object', () => {
expect(component.model).toEqual(new Mail)
})

describe('when composing a new message', () => {
it('should initialize an empty model "to" field', async() => {
await component.ngOnInit();
expect(component.model.to).toBe('')
})

it('should initialize the model "from" field with currentAccount', async() => {
component.currentAccount = currentAccount
await component.ngOnInit();
expect(component.model.from).toBe(currentAccount)

component.currentAccount = currentAccount2
await component.ngOnInit();
fixture.detectChanges()
expect(component.model.from).toBe(currentAccount2)
})

it('should initialize an empty model "subject" field', async() => {
await component.ngOnInit();
expect(component.model.subject).toBe('')
})

it('should initialize an empty model "body" field', async() => {
await component.ngOnInit();
expect(component.model.body).toBe('')
})
});

describe('when composing a reply', () => {
beforeEach(()=>{
component.currentMessage = mailchainTestService.inboundMessage();
})

it('should initialize the model "from" field with the recipient address', async() => {
await component.ngOnInit();
expect(component.model.from).toBe('0x0123456789abcdef0123456789abcdef01234567')
})

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 initialize the model "body" field with the original message field', async() => {
let response = "\r\n\r\n>From: <0x0123456789012345678901234567890123456789@testnet.ethereum>\r\n>Date: 2019-06-07T14:53:36Z\r\n>To: <0x0123456789abcdef0123456789abcdef01234567@testnet.ethereum>\r\n>Subject: Re: Mailchain Test!\r\n>\r\n>A body"

await component.ngOnInit();
expect(JSON.stringify(component.model.body)).toBe(JSON.stringify(response))
})
});

describe('setFromAddressList', () => {
it('should set the fromAddresses', async() => {
expect(component.fromAddresses).toEqual([])
await component.ngOnInit();
expect(component.fromAddresses).toEqual(addresses)

})
});
});
});

describe('returnToInboxMessages', () => {
it('should call goToInboxMessages.emit() to change the view to "messages"', () => {
spyOn(component.goToInboxMessages,'emit')

component.returnToInboxMessages()
expect(component.goToInboxMessages.emit).toHaveBeenCalledWith('')
})
});
describe('returnToMessage', () => {
it('should call goToInboxMessages.emit() to change the view to "messages" if there is no currentMessage', () => {
spyOn(component.goToInboxMessages,'emit')

component.returnToMessage()
expect(component.goToInboxMessages.emit).toHaveBeenCalledWith('')
})
it('should call openMessage.emit(`currentMessage`) to change the view to "messages" if there is a currentMessage', () => {
spyOn(component.openMessage,'emit')
component.currentMessage = mailchainTestService.inboundMessage();

component.returnToMessage()
expect(component.openMessage.emit).toHaveBeenCalledWith(component.currentMessage)
})
});
describe('supressEnterPropagation', () => {
it('should stop event propagation when Enter is pressed', () => {
let $event = new KeyboardEvent('keydown', {'code': 'Enter'})
spyOn($event,'stopPropagation')
component.supressEnterPropagation($event)
expect($event.stopPropagation).toHaveBeenCalled()
})
});

describe('onSubmit', () => {
let mail = new Mail
mail.to = ''
mail.from = ''
mail.subject = ''
mail.body = ''
mail.publicKey = "1234567890abcd"

let outboundMail = new OutboundMail
outboundMail.message = {
body: 'This is a test message',
headers: {
"from": '0x0123456789abcdef0123456789abcdef01234567',
"reply-to": '0x0123456789abcdef0123456789abcdef01234567',
"to": '0x0123456789012345678901234567890123456789'
},
"public-key": "1234567890abcd",
subject: 'Test Message'
}

beforeEach(()=>{
component.model.to = currentAccount
component.model.from = currentAccount2
component.model.subject = "Test Message"
component.model.body = "This is a test message"
component.currentNetwork = 'testnet'

spyOn(publicKeyService,"getPublicKeyFromAddress").and.callFake( ()=>{
return of({"public_key": '1234567890abcd'})
});
spyOn(sendService,"sendMail").and.callFake( ()=>{
return of(['ok'])
});

spyOn(mailchainService,"generateMail").and.callFake(() => {
return outboundMail
})
})

it('should get the public key for an address', async() => {
component.onSubmit();

expect(publicKeyService.getPublicKeyFromAddress).toHaveBeenCalledWith(currentAccount,'testnet')
})

it('should send a message using the sendService', async() => {

component.onSubmit();
expect(sendService.sendMail).toHaveBeenCalledWith(outboundMail,'testnet')
})

it('should generate a message', () => {

component.onSubmit();
expect(mailchainService.generateMail).toHaveBeenCalledWith(mail)

})

it('should reinitialize the message after sending', () => {

component.onSubmit();
expect(component.model).toEqual(mail)
})
it('should call returnToInboxMessages after sending', () => {
spyOn(component,"returnToInboxMessages")
component.onSubmit();
expect(component.returnToInboxMessages).toHaveBeenCalled()
})
xit('should validate form fields', () => {
// expect()
})
xit('should handle public key lookup failure', () => {
// expect()
})
});


});
48 changes: 30 additions & 18 deletions src/app/inbox/inbox-compose/inbox-compose.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import { AddressesService } from 'src/app/services/mailchain/addresses/addresses
})

export class InboxComposeComponent implements OnInit {
@Input() currentMessage: any;
@Input() currentAccount: string;
@Input() currentNetwork: string;
@Input() currentMessage: any;

@Output() openMessage = new EventEmitter();
@Output() goToInboxMessages = new EventEmitter();
Expand All @@ -31,6 +32,9 @@ export class InboxComposeComponent implements OnInit {
private addressesService: AddressesService,
) { }

/**
* Initialize empty values for the message model
*/
private initMail() {
this.model.to = ""
this.model.from = ""
Expand All @@ -53,7 +57,7 @@ export class InboxComposeComponent implements OnInit {
}

/**
* Go back to the inbox-messages view
* If there is a currentMessage, call the openMessage.emit to go back to the inbox-messages view; Otherwise, call the functin to return to inbox view
*/
public returnToMessage(): void {
if (this.currentMessage == undefined) {
Expand All @@ -71,14 +75,13 @@ export class InboxComposeComponent implements OnInit {
}

/**
* Sets the first available address in the `from` dropdown
* Sets the currentAccount as the address in the `from` dropdown
* -or-
* When replying, sets the from address as the address the message was sent to
*/
private setFirstOptionInFromAddressDropdown(){
// Set first option in dropdown
if ( this.fromAddresses[0] != undefined ) {
this.model.from = this.fromAddresses[0]
private setCurrentAccountInFromAddressDropdown(){
if ( this.currentAccount != undefined ) {
this.model.from = this.currentAccount
}
}

Expand All @@ -91,15 +94,23 @@ export class InboxComposeComponent implements OnInit {
async ngOnInit(): Promise<void> {
await this.setFromAddressList()
this.initMail()
this.setFirstOptionInFromAddressDropdown()
this.setCurrentAccountInFromAddressDropdown()
this.handleReplyFields()

}

/**
* Set the fields for a reply
*/
private handleReplyFields(){
if ( this.currentMessage && this.currentMessage.headers ) {
var messageFrom: string = "",
messageReplyTo: string = "",
messageDate: string = "",
messageTo: string = "",
messageSubject: string = "",
messageBody: string = ""

var messageFrom: string = "",
messageReplyTo: string = "",
messageDate: string = "",
messageTo: string = "",
messageSubject: string = "",
messageBody: string = ""

if (this.currentMessage.headers["from"]) {
messageFrom = '\r\n\r\n>From: ' + this.currentMessage.headers["from"] + "\r\n"
Expand Down Expand Up @@ -151,19 +162,19 @@ export class InboxComposeComponent implements OnInit {

/**
* onSubmit sends email to the local service. It includes the reset form to handle errors and resets.
* @param form is the form being sent to the local service
*/
public onSubmit(form: NgForm) {
public onSubmit() {
this.sendMessagesDisabled = true
var self = this

this.publicKeyService.getPublicKeyFromAddress(
this.model.to,
this.currentNetwork
).subscribe(res => {

this.model.publicKey = res["public_key"]
var outboundMail = this.generateMessage(this.model)

this.sendMessage(outboundMail).subscribe(res => {
self.initMail();
self.returnToInboxMessages();
Expand All @@ -183,8 +194,9 @@ export class InboxComposeComponent implements OnInit {
* Sends the OutboundMail object on the currently selected network
* @param outboundMail The OutboundMail object
*/
private sendMessage(outboundMail: OutboundMail) {
private sendMessage(outboundMail: OutboundMail) {
let network = this.currentNetwork

return this.sendService.sendMail(outboundMail, network)
}
}
Expand Down
Loading

0 comments on commit e2d7ecb

Please sign in to comment.