Commit bf888b94 authored by Laurent's avatar Laurent

Add Symphony connector

parent bc6941dd
......@@ -137,6 +137,15 @@ export abstract class PortalAdapter {
}
protected _encodeForm(form: Object): string {
let datas = [];
for(let key in form)
datas.push([encodeURIComponent(key), encodeURIComponent(form[key])].join('='));
return datas.join('&');
}
protected abstract _signIn(account: Account): Promise<any>;
public abstract getIdentifier(): string;
......
......@@ -7,4 +7,5 @@ export {Ermes} from './ermes';
export {Koha} from './koha';
export {KohaCas} from './koha-cas';
export {InMedia} from './inmedia';
export {Symphony} from './symphony';
export {Autodetect} from './autodetect';
......@@ -280,15 +280,6 @@ export class OrpheeMedia extends PortalAdapter {
}
protected _encodeForm(form: Object): string {
let datas = [];
for(let key in form)
datas.push([encodeURIComponent(key), encodeURIComponent(form[key])].join('='));
return datas.join('&');
}
protected _checkConnected(account, response): Promise<any> {
let $ = cheerio.load(response.content.toString());
......@@ -365,7 +356,6 @@ export class OrpheeMedia extends PortalAdapter {
.setRecordId(record_id)
.setRecordUrl(account.getUrl() + '/index.php?option=com_opac&task=DetailNtcFull&num_ntc=' + record_id)
.setDateDue(date_due.split('/').reverse().join('-'));
loans.push(loan);
});
......
import {PortalAdapter} from './adapter';
import * as cheerio from 'cheerio';
import {Account, Loan} from '../../models';
import {WrongLoginPassword} from './wrong-login-password';
import * as UrlParse from 'url-parse';
export class Symphony extends PortalAdapter {
public getIdentifier():string {
return 'symphony';
}
public getLabel():string {
return 'Symphony';
}
public canHandleWebsite($): boolean {
return $('form[action*="/web2/tramp2.exe"]').length;
}
public _signIn(account: Account): Promise<any> {
if (!(account.credentials['login'] && account.credentials['password']))
return Promise.reject(new WrongLoginPassword());
return this
._openSession(account)
.then ( ($) => {
if ($('input[name="userid"]').length > 0)
return Promise.reject(new WrongLoginPassword());
account.beConnected();
return Promise.resolve();
})
}
protected _openSession(account: Account): Promise<any> {
let base_url = new UrlParse(account.getUrl()).origin;
return this
.request(account, { url: account.getUrl() })
.then( (response) => {
let $ = cheerio.load(response.content.toString());
let account_link = $('a[href*="?screen=MyAccount.html"]');
return this
.request(account, { url: base_url + account_link.attr('href') })
})
.then( (response) => {
let $ = cheerio.load(response.content.toString());
let form = $('form[action*=login_when_needed]');
let login_data = {
fail_screen: 'LoginOTFFailed.html',
screen: 'MyAccount.html',
server: '',
item: '',
item_source: '',
userid: account.credentials['login'],
pin: account.credentials['password']
};
return this
.request(account,
{ url: base_url + form.attr('action'),
method: 'POST',
content: this._encodeForm(login_data),
headers: {"Content-Type": "application/x-www-form-urlencoded"}
})
})
.then( (response) => {
return cheerio.load(response.content.toString());
})
}
protected _fetchLoans(account: Account): Promise<Array<Loan>> {
return this
._openSession(account)
.then( ($) => {
let loans = new Array<Loan>();
let rows = $('div#panel2 table:first-child + table tr + tr');
rows.each( (i, element) => {
let node = $(element);
let title = node.find('td:nth-child(2) a').text().trim();
let author = node.find('td:nth-child(3)').text().trim();
let date_due = node.find('td:nth-child(6)').text().trim().split(',')[0];
let loan = (new Loan())
.setTitle(title)
.setAuthor(author)
.setDateDue(date_due
.split('/')
.reverse()
.map( (part) => {
return part.padStart(2, '0');
})
.join('-'));
loans.push(loan);
});
return loans;
});
}
}
declare var expect: any;
import {HTTPScenario} from './http-scenario';
export class SymphonySignInWithSuccessfulLogin extends HTTPScenario {
public constructor(base_url: string) {
super();
this
.expect({ url: base_url + '/web2/tramp2.exe/log_in?setting_key=BMT1' },
{ content: this.homePage() })
.expect({ url: base_url + '/web2/tramp2.exe/goto/A05ppu9t.000?screen=MyAccount.html' },
{ content: this.loginPage() })
.expect({ url: base_url + '/web2/tramp2.exe/login_when_needed/A05qsq7s.000',
method: 'POST',
content: 'fail_screen=LoginOTFFailed.html&screen=MyAccount.html&server=&item=&item_source=&userid=marco&pin=polo',
headers: {"Content-Type": "application/x-www-form-urlencoded"} },
{ content: this.accountPage() })
.expect({ url: base_url + '/web2/tramp2.exe/log_in?setting_key=BMT1' },
{ content: this.homePage() })
.expect({ url: base_url + '/web2/tramp2.exe/goto/A05ppu9t.000?screen=MyAccount.html' },
{ content: this.loginPage() })
.expect({ url: base_url + '/web2/tramp2.exe/login_when_needed/A05qsq7s.000',
method: 'POST',
content: 'fail_screen=LoginOTFFailed.html&screen=MyAccount.html&server=&item=&item_source=&userid=marco&pin=polo',
headers: {"Content-Type": "application/x-www-form-urlencoded"} },
{ content: this.accountPage() })
}
public homePage(): string {
return this._encapsulate('\
<a class="moncompte" href="/web2/tramp2.exe/goto/A05ppu9t.000?screen=MyAccount.html">\
<span>Mon compte</span>\
</a>')
}
public loginPage(): string {
return this._encapsulate('\
<form name="loginWN" action="/web2/tramp2.exe/login_when_needed/A05qsq7s.000" method="POST" enctype="application/x-www-form-urlencoded">\
<input name="fail_screen" value="LoginOTFFailed.html" type="hidden">\
<input name="screen" value="MyAccount.html" type="hidden">\
<input name="server" value="" type="hidden">\
<input name="item" value="" type="hidden">\
<input name="item_source" value="" type="hidden">\
<table cellspacing="0" cellpadding="0" align="center">\
<tbody>\
<tr>\
<td><input name="userid" ></td>\
<td><input name="pin" ></td>\
</tr>\
</tbody>\
</table>\
</form>')
}
public accountPage(): string {
return this._encapsulate('\
<table title="" width="100%" cellspacing="10" cellpadding="0" border="0" align="center">\
<tbody>\
<tr>\
<td class="defaultstyle">\
<table width="100%" cellspacing="0" cellpadding="0" border="0">\
<tbody><tr>\
<td> <h2>DUVAL, Claire</h2> </td>\
</tr>\
</tbody></table>\
<table width="100%" cellspacing="0" cellpadding="2" border="0"></table>\
<div id="panel1" class="panel" style="display: block;"> \
<div class="bibinfo">\
<table width="100%" cellspacing="0" cellpadding="2" border="0"></table> \
<table valign="top" width="100%"> \
<tbody><tr><td class="searchcontent">\
Votre numéro d\'abonné est : <strong>00170006741442</strong> \
</td></tr></tbody></table>\
</div>\
</div> \
<div id="panel2" class="panel" style="display: none;">\
<div class="bibinfo"> \
<form action="/web2/tramp2.exe/form/A05rc8n4.000" method="post" enctype="application/x-www-form-urlencoded">\
<table width="100%" cellspacing="0" cellpadding="2" border="0"></table> \
<table width="100%" cellspacing="0" cellpadding="2" border="2">\
<tbody>\
<tr>\
<th class="subheader"><strong></strong></th>\
<th class="subheader"><strong>Titre</strong></th>\
<th class="subheader"><strong>Auteur</strong></th>\
<th class="subheader"><strong>Type de document</strong></th>\
<th class="subheader"><strong>Emprunté à</strong></th>\
<th class="subheader"><strong>A rendre le</strong></th>\
<th class="subheader" align="center"><strong>Retard</strong></th>\
<th class="subheader"><strong>Renouvellements</strong></th>\
</tr>\
<tr>\
<td class="docmoncompte">\
<input name="HASNOW" value="30170025349163:1" type="CHECKBOX">&nbsp;\
</td>\
<td class="docmoncompte">\
<a href="/web2/tramp2.exe/do_keyword_search/A05rc8n4.000?servers=1home&amp;query=(TI L\'expérience extraordinaire)">L\'expérience extraordinaire</a>\
</td>\
<td class="docmoncompte">\
Fraipont, Céline\
</td>\
<td class="docmoncompte">\
<i>_TEXTP</i>\
&nbsp;\
</td>\
<td class="docmoncompte">\
EMP\
</td>\
<td class="docmoncompte">\
<strong>2/7/2018,23:59</strong>\
&nbsp;\
</td>\
<td class="docmoncompte">\
<strong></strong>\
&nbsp;\
</td>\
<td class="docmoncompte">\
&nbsp;\
</td>\
</tr>\
<tr>\
<td class="docmoncompte">\
<input name="HASNOW" value="30170027846513:1" type="CHECKBOX">&nbsp;\
</td>\
<td class="docmoncompte">\
<a href="/web2/tramp2.exe/do_keyword_search/A05rc8n4.000?servers=1home&amp;query=(TI Le trésor de Coconut)">Le trésor de Coconut</a>\
&nbsp;\
</td>\
<td class="docmoncompte" width="20%">\
Ponton, Carole\
</td>\
<td class="docmoncompte">\
<i>_TEXTP</i>\
</td>\
<td class="docmoncompte">\
EMP\
</td>\
<td class="docmoncompte">\
<strong>4/7/2018,23:59</strong>\
&nbsp;\
</td>\
<td class="docmoncompte"> </td>\
<td class="docmoncompte">\
</td>\
</tr>\
</tbody>\
</table>\
</form>\
</div>\
</div> \
</td>\
</tr>\
</tbody>\
</table>');
}
}
declare var describe, expect, it, before, beforeEach, chai: any;
import {Loan, Account, Database, Portal} from '../../models/';
import {Symphony} from '../../models/';
import {SymphonySignInWithSuccessfulLogin} from './symphony-fixtures';
describe('Account on Symphony', () => {
let adapter: Symphony;
let db: Database;
let account: Account;
beforeEach( () => {
db = Database.open('testdb').clear();
adapter = new Symphony();
account = (new Account())
.setUrl('http://symphony.fr/web2/tramp2.exe/log_in?setting_key=BMT1')
.setCredentials({login: 'marco',
password: 'polo',
portal: 'symphony'});
db.save(account);
})
describe('With successful Login scenario', () => {
it('db should have two loans', () => {
let http = new SymphonySignInWithSuccessfulLogin('http://symphony.fr');
return adapter.setHTTP(http).refresh(account).then(() => {
let loans = account.findLoans(db);
expect(loans).to.have.lengthOf(2);
expect(loans[0].getTitle()).to.include('L\'expérience extraordinaire');
expect(loans[0].getAuthor()).to.equals('Fraipont, Céline');
expect(loans[0].getDateDue()).to.equals('2018-07-02');
});
})
})
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment