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

Commit

Permalink
Merge branch 'mailchain-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
sa3664 committed Jun 26, 2021
2 parents 61b39b8 + ec59b4a commit 59c8e78
Show file tree
Hide file tree
Showing 17 changed files with 21,247 additions and 73 deletions.
20,972 changes: 20,944 additions & 28 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "mailchain-web",
"version": "0.0.15",
"version": "0.0.16",
"scripts": {
"ng": "ng",
"start": "ng serve",
Expand Down
5 changes: 3 additions & 2 deletions src/app/inbox/inbox-compose/inbox-compose.component.html
Expand Up @@ -35,7 +35,8 @@ <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"

<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}}
Expand All @@ -59,7 +60,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"
placeholder="e.g. 0x0000...0000 or mailchain.eth" [(ngModel)]="messageToField" [disabled]="isReply"
(keyup)="recipientResolve($event)">
</div>
</div>
Expand Down
104 changes: 84 additions & 20 deletions src/app/inbox/inbox-compose/inbox-compose.component.spec.ts
Expand Up @@ -126,6 +126,17 @@ describe('InboxComposeComponent', () => {
expect(component.model.from).toBe(currentAccount2)
})

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

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

it('should initialize an empty model "subject" field', async () => {
await component.ngOnInit();
expect(component.model.subject).toBe('')
Expand Down Expand Up @@ -174,29 +185,62 @@ describe('InboxComposeComponent', () => {
});


describe('when composing a plaintext reply', () => {
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')
})
xit('should disable the model "from" field on page so the address cannot be changed', async () => {
// TODO
await component.ngOnInit();
// expect(component.mailForm).toBe('0x0123456789abcdef0123456789abcdef01234567')
})

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

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!')
})






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


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: Mailchain Test!\r\n>\r\n>A body"
let response = "\r\n\r\n>From: <0x0123456789012345678901234567890123456789@testnet.ethereum>\r\n>Reply To: <0xABCDEABCDE012345678901234567890123456789@testnet.ethereum>\r\n>Date: 2019-06-07T14:53:36Z\r\n>To: <0x0123456789abcdef0123456789abcdef01234567@testnet.ethereum>\r\n>Subject: Mailchain Test!\r\n>\r\n>A body"

await component.ngOnInit();
expect(JSON.stringify(component.model.body)).toBe(JSON.stringify(response))
Expand All @@ -209,24 +253,9 @@ describe('InboxComposeComponent', () => {
component.currentMessage.headers["content-type"] = "text/html; charset=\"UTF-8\""
})

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 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!')
})


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>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>"
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>"

await component.ngOnInit();
expect(JSON.stringify(component.model.body)).toBe(JSON.stringify(response))
Expand Down Expand Up @@ -365,6 +394,21 @@ describe('InboxComposeComponent', () => {
})
})

describe('evaluateReply', () => {
it('should set isReply to false when composing a new', () => {
component.ngOnInit();
component.evaluateReply()
expect(component.isReply).toBeFalse()
})
it('should set isReply to true when composing an existing message', () => {
component.currentMessage = mailchainTestService.inboundMessage();
component.ngOnInit();
component.evaluateReply()
expect(component.isReply).toBeTrue()
})

})

describe('setupRecipientAddressLookupSubscription', () => {
xit('should ', () => {
// todo: needs help
Expand All @@ -379,6 +423,14 @@ describe('InboxComposeComponent', () => {
})
})

describe('resetModelReplyToField', () => {
it('should reset the model.replyTo field', () => {
component.model.replyTo = "0x0000000"
component.resetModelReplyToField()
expect(component.model.replyTo).toEqual("")
})
})

describe('resolveAddress', () => {
describe('in ethereum', () => {
it('should call nameserviceService.resolveName if given a name-like value', () => {
Expand Down Expand Up @@ -427,6 +479,18 @@ describe('InboxComposeComponent', () => {
describe('in substrate', () => {
it('should return an observable with body containing address hash if given an address-like value', async () => {
component.currentProtocol = 'substrate'
let currentAccount = "15GJj1Lg6kL5bsN49fV1gcd4ezvU6wafsfZn3oZ7bf7EeM5U"
let obs = await component.resolveAddress(currentAccount)
let expectedBody = { address: currentAccount }
obs.subscribe(res => {
expect(res['body']).toEqual(expectedBody)
})
})
})
describe('in algorand', () => {
it('should return an observable with body containing address hash if given an address-like value', async () => {
component.currentProtocol = 'algorand'
let currentAccount = "UWH6MCLMZSD2UYWTJVKFKX6JMTX2TGXAOYPUBNHFFQFBBVJULXJXZJNPBU"
let obs = await component.resolveAddress(currentAccount)
let expectedBody = { address: currentAccount }
obs.subscribe(res => {
Expand Down
43 changes: 40 additions & 3 deletions src/app/inbox/inbox-compose/inbox-compose.component.ts
Expand Up @@ -57,6 +57,7 @@ export class InboxComposeComponent implements OnInit {
public contentTypeSwitchLabel: string = ""
public envelopeType
public envelopeDescription
public isReply: boolean = false

@ViewChild('editor') public editorComponent: CKEditorComponent;

Expand All @@ -79,6 +80,7 @@ export class InboxComposeComponent implements OnInit {
private initMail() {
this.model.to = ""
this.model.from = ""
this.model.replyTo = ""
this.model.subject = ""
this.model.body = ""

Expand Down Expand Up @@ -223,6 +225,7 @@ export class InboxComposeComponent implements OnInit {
res.subscribe(val => {
let address = val['body']['address']
if (
(this.currentProtocol == 'algorand' && this.mailchainService.validateAlgorandAddress(address)) ||
(this.currentProtocol == 'ethereum' && this.mailchainService.validateEthAddress(address)) ||
(this.currentProtocol == 'substrate' && this.mailchainService.validateSubstrateAddress(address))
) {
Expand All @@ -247,6 +250,13 @@ export class InboxComposeComponent implements OnInit {
this.model.to = ""
}

/**
* resetModelReplyToField resets the reply-to field in the model
*/
public resetModelReplyToField() {
this.model.replyTo = ""
}

/**
* Determines whether an address is:
* * a public address,
Expand Down Expand Up @@ -284,6 +294,20 @@ export class InboxComposeComponent implements OnInit {
{ body: { address: '' } }
)
}
} else if (this.currentProtocol == 'algorand') {
if (this.mailchainService.validateAlgorandAddress(value)) {
returnObs = of(
{ body: { address: value } }
)
} else {
returnObs = of(
{ body: { address: '' } }
)
}
} else { // return the address anyway
returnObs = of(
{ body: { address: value } }
)
};

return returnObs
Expand Down Expand Up @@ -322,7 +346,7 @@ export class InboxComposeComponent implements OnInit {
*/
private setCurrentAccountInFromAddressDropdown() {
if (this.currentAccount != undefined) {
this.model.from = this.currentAccount
this.model.replyTo = this.model.from = this.currentAccount
}
}

Expand Down Expand Up @@ -350,6 +374,7 @@ export class InboxComposeComponent implements OnInit {
this.initEditor()
this.setCurrentAccountInFromAddressDropdown()
this.setFirstEnvelopeInEnvelopeDropdown()
this.evaluateReply()
this.handleReplyFields()
this.setupRecipientAddressLookupSubscription()
await this.setBalance()
Expand Down Expand Up @@ -451,6 +476,13 @@ export class InboxComposeComponent implements OnInit {
messageBody
}

/**
* Evalute if the message is a reply or a new message
*/
evaluateReply() {
this.isReply = (this.currentMessage && this.currentMessage.headers) ? true : false
}

/**
* Set the fields for a reply
*/
Expand All @@ -463,10 +495,15 @@ export class InboxComposeComponent implements OnInit {
this.handleReplyInPlaintext()
}

this.model.to = this.mailchainService.parseAddressFromMailchain(this.currentProtocol, this.currentMessage.headers["from"])
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.from = this.mailchainService.parseAddressFromMailchain(this.currentProtocol, this.currentMessage.headers["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
Expand Up @@ -245,6 +245,7 @@ describe('InboxMessagesComponent', () => {
let protocol = 'ethereum'
let addrIcon1 = mailchainService.generateIdenticon(protocol, address1);
let addrIcon2 = mailchainService.generateIdenticon(protocol, address2);
let defaultIcon = mailchainService.mailchainLogoIdenticonImage()
messages.forEach(msg => {
component.addMailToInboxMessages(msg)
})
Expand All @@ -257,7 +258,7 @@ describe('InboxMessagesComponent', () => {
} else if ([3,4,5].includes(index)) {
icon = addrIcon1
} else if ([8,9].includes(index)) {
icon = '' // SUBSTRATE not supported
icon = defaultIcon // SUBSTRATE not supported
};

expect(val['senderIdenticon']).toEqual(icon);
Expand Down
1 change: 1 addition & 0 deletions src/app/models/mail.ts
@@ -1,6 +1,7 @@
export class Mail {
public to: string = "";
public from: string = "";
public replyTo: string = "";
public subject: string = "";
public body: string = "";
public publicKey: string = "";
Expand Down
Expand Up @@ -103,6 +103,14 @@ MailchainTestService

expect(await localStorageNameserviceService.getCurrentNameserviceDomainEnabled()).toEqual("false");
});
it('should look up the current nameservice domain enabled status from protocols endpoint if not defined, expecting `false` (algorand)', async () => {
sessionStorage.removeItem('currentNameserviceDomainEnabled');
sessionStorage.setItem('currentProtocol', 'algorand')
sessionStorage.setItem('currentNetwork', 'mainnet')
spyOn(protocolsService, 'getProtocols').and.returnValue(mailchainTestService.protocolsServerResponse())

expect(await localStorageNameserviceService.getCurrentNameserviceDomainEnabled()).toEqual("false");
});

});
describe('setCurrentNameserviceDomainEnabled', () => {
Expand Down
Expand Up @@ -35,7 +35,7 @@ describe('LocalStorageProtocolService', () => {

describe('getCurrentProtocol', () => {
it('should retrieve the currentProtocol when NO value is stored', async () => {
expect(await localStorageProtocolService.getCurrentProtocol()).toEqual(mailchainTestService.protocolsServerResponse()["protocols"][0]["name"])
expect(await localStorageProtocolService.getCurrentProtocol()).toEqual(mailchainTestService.protocolsServerResponse()["protocols"][1]["name"])
});

it('should retrieve the currentProtocol when a value is stored', async () => {
Expand Down
Expand Up @@ -210,7 +210,7 @@ describe('ConnectivityService', () => {
spyOn(protocolsService, 'getProtocolsResponse').and.returnValue(expectedProtocolsObs);

await connectivityService.getApiProtocolsAvailability().then(res => {
expect(res["protocols"]).toEqual(2)
expect(res["protocols"]).toEqual(3)
expect(res["status"]).toEqual("ok")
expect(res["code"]).toEqual(200)
expect(res["message"]).toEqual("OK")
Expand Down

0 comments on commit 59c8e78

Please sign in to comment.