opds-web-client
Version:
721 lines (720 loc) • 44.8 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var chai_1 = require("chai");
var sinon_1 = require("sinon");
var React = require("react");
var PropTypes = require("prop-types");
var enzyme_1 = require("enzyme");
var Root_1 = require("../Root");
var Breadcrumbs_1 = require("../Breadcrumbs");
var Collection_1 = require("../Collection");
var UrlForm_1 = require("../UrlForm");
var BookDetails_1 = require("../BookDetails");
var SkipNavigationLink_1 = require("../SkipNavigationLink");
var CatalogLink_1 = require("../CatalogLink");
var Search_1 = require("../Search");
var LoadingIndicator_1 = require("../LoadingIndicator");
var ErrorMessage_1 = require("../ErrorMessage");
var AuthProviderSelectionForm_1 = require("../AuthProviderSelectionForm");
var collectionData_1 = require("./collectionData");
var routing_1 = require("../../__mocks__/routing");
var book = {
id: "urn:librarysimplified.org/terms/id/3M%20ID/crrmnr9",
title: "The Mayan Secrets",
authors: ["Clive Cussler", "Thomas Perry"],
summary: "<strong>Sam and Remi Fargo race for treasure—and survival—in this lightning-paced new adventure from #1<i> New York Times</i> bestselling author Clive Cussler.</strong><br />Husband-and-wife team Sam and Remi Fargo are in Mexico when they come upon a remarkable discovery—the mummified remainsof a man clutching an ancient sealed pot. Within the pot is a Mayan book larger than any known before.<br />The book contains astonishing information about the Mayans, their cities, and about mankind itself. The secrets are so powerful that some people would do anything to possess them—as the Fargos are about to find out.",
imageUrl: "https://dlotdqc6pnwqb.cloudfront.net/3M/crrmnr9/cover.jpg",
openAccessLinks: [
{ url: "secrets.epub", type: "application/epub+zip" },
{ url: "secrets.mobi", type: "application/x-mobipocket-ebook" }
],
borrowUrl: "borrow url",
publisher: "Penguin Publishing Group",
published: "February 29, 2016",
categories: ["category 1", "category 2"],
series: {
name: "Fake Series"
},
language: "de",
raw: {
$: { "schema:additionalType": { value: "http://bib.schema.org/Audiobook" } }
}
};
var setCollectionAndBookPromise = new Promise(function (resolve, reject) {
resolve({
collectionData: null,
bookData: null
});
});
var mockSetCollectionAndBook = (0, sinon_1.stub)().returns(setCollectionAndBookPromise);
var fulfillBook = function (url) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, new Blob()];
}); }); };
var updateBook = function (url) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, book];
}); }); };
var indirectFulfillBook = function (url, type) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, "test value"];
}); }); };
var setPreference = function () { return null; };
describe("Root", function () {
it("shows skip navigation link", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var links = wrapper.find(SkipNavigationLink_1.default);
(0, chai_1.expect)(links.length).to.equal(1);
});
it("contains main element", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var main = wrapper.find("main");
(0, chai_1.expect)(main.props().role).to.equal("main");
});
it("shows search and treats it as top-level", function () {
var collectionData = Object.assign({}, collectionData_1.ungroupedCollectionData, {
search: {
url: "test search url",
searchData: {
description: "description",
shortName: "shortName",
template: function (s) { return s; }
}
}
});
var fetchSearchDescription = function (url) { };
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionData: collectionData, fetchSearchDescription: fetchSearchDescription }));
var search = wrapper.find(Search_1.default);
(0, chai_1.expect)(search.props().url).to.equal(collectionData.search.url);
(0, chai_1.expect)(search.props().searchData).to.equal(collectionData.search.searchData);
(0, chai_1.expect)(search.props().fetchSearchDescription).to.equal(fetchSearchDescription);
});
it("shows a collection if props include collectionData", function () {
var collectionData = collectionData_1.groupedCollectionData;
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionData: collectionData }));
var collections = wrapper.find(Collection_1.default);
(0, chai_1.expect)(collections.length).to.equal(1);
(0, chai_1.expect)(collections.first().props().collection).to.deep.equal(collectionData);
});
it("shows a (non-grouped) collection with loans if props include collectionData and loans", function () {
var collectionData = collectionData_1.ungroupedCollectionData;
// One book is on loan.
var loan = Object.assign({}, collectionData.books[1], {
fulfillmentLinks: [{ url: "fulfill", type: "text/html" }]
});
var loans = [loan];
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionData: collectionData, loans: loans }));
var collections = wrapper.find(Collection_1.default);
(0, chai_1.expect)(collections.length).to.equal(1);
var expectedBooks = [
collectionData.books[0],
loan,
collectionData.books[2]
];
var expectedCollection = Object.assign({}, collectionData, {
books: expectedBooks
});
(0, chai_1.expect)(collections.first().props().collection).to.deep.equal(expectedCollection);
});
it("shows a url form if no collection url or book url", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var urlForms = wrapper.find(UrlForm_1.default);
(0, chai_1.expect)(urlForms.length).to.equal(1);
});
it("doesn't show a url form if collection url", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionUrl: "test", setCollectionAndBook: mockSetCollectionAndBook }));
var urlForms = wrapper.find(UrlForm_1.default);
(0, chai_1.expect)(urlForms.length).to.equal(0);
});
it("doesn't show a url form if book url", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, bookUrl: "test", setCollectionAndBook: mockSetCollectionAndBook }));
var urlForms = wrapper.find(UrlForm_1.default);
(0, chai_1.expect)(urlForms.length).to.equal(0);
});
it("fetches a collection url on mount", function () {
var collectionUrl = "http://feedbooks.github.io/opds-test-catalog/catalog/acquisition/blocks.xml";
var setCollectionAndBook = (0, sinon_1.stub)().returns(setCollectionAndBookPromise);
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionUrl: collectionUrl, setCollectionAndBook: setCollectionAndBook }));
(0, chai_1.expect)(setCollectionAndBook.callCount).to.equal(1);
(0, chai_1.expect)(setCollectionAndBook.args[0][0]).to.equal(collectionUrl);
(0, chai_1.expect)(setCollectionAndBook.args[0][1]).not.to.be.ok;
});
it("fetches a book url on mount", function () {
var bookUrl = "http://example.com/book";
var setCollectionAndBook = (0, sinon_1.stub)().returns(setCollectionAndBookPromise);
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { bookUrl: bookUrl, setCollectionAndBook: setCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
(0, chai_1.expect)(setCollectionAndBook.callCount).to.equal(1);
(0, chai_1.expect)(setCollectionAndBook.args[0][0]).not.to.be.ok;
(0, chai_1.expect)(setCollectionAndBook.args[0][1]).to.equal(bookUrl);
});
it("fetches loans on mount", function (done) {
var collectionUrl = "http://feedbooks.github.io/opds-test-catalog/catalog/acquisition/blocks.xml";
var setCollectionAndBook = function (collectionUrl, bookUrl) {
return new Promise(function (resolve, reject) {
return resolve({
collectionData: Object.assign({}, collectionData_1.ungroupedCollectionData, {
shelfUrl: "loans url"
}),
bookData: null
});
});
};
var fetchLoans = (0, sinon_1.stub)();
var credentials = { provider: "test", credentials: "credentials" };
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionUrl: collectionUrl, setCollectionAndBook: setCollectionAndBook, fetchLoans: fetchLoans, authCredentials: credentials, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
wrapper.instance()
.componentWillMount()
.then(function () {
var count = fetchLoans.callCount;
(0, chai_1.expect)(fetchLoans.args[count - 1][0]).to.equal("loans url");
done();
})
.catch(function (err) {
console.log(err);
throw err;
});
});
it("updates page title on mount", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { pageTitleTemplate: function (collection, book) { return "page title"; }, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
(0, chai_1.expect)(document.title).to.equal("page title");
});
it("sets auth credentials on mount", function () {
var credentials = { provider: "test", credentials: "credentials" };
var saveAuthCredentials = (0, sinon_1.stub)();
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { saveAuthCredentials: saveAuthCredentials, authCredentials: credentials, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
(0, chai_1.expect)(saveAuthCredentials.callCount).to.equal(1);
(0, chai_1.expect)(saveAuthCredentials.args[0][0]).to.equal(credentials);
});
var basicProps = {
fulfillBook: fulfillBook,
indirectFulfillBook: indirectFulfillBook,
updateBook: updateBook,
setPreference: setPreference
};
it("checks for credentials on mount", function () {
var credentials = { provider: "test", credentials: "credentials" };
var plugin = {
type: "test",
lookForCredentials: (0, sinon_1.stub)().returns({ credentials: credentials }),
formComponent: (0, sinon_1.stub)(),
buttonComponent: (0, sinon_1.stub)()
};
var propsWithAuthPlugin = __assign({ authPlugins: [plugin], saveAuthCredentials: (0, sinon_1.stub)() }, basicProps);
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, __assign({}, propsWithAuthPlugin)));
(0, chai_1.expect)(plugin.lookForCredentials.callCount).to.equal(1);
(0, chai_1.expect)(propsWithAuthPlugin.saveAuthCredentials.callCount).to.equal(1);
(0, chai_1.expect)(propsWithAuthPlugin.saveAuthCredentials.args[0][0]).to.deep.equal(credentials);
});
it("sets auth error in state on mount if lookForCredentials returns an error", function () {
var plugin = {
type: "test",
lookForCredentials: (0, sinon_1.stub)().returns({ error: "error!" }),
formComponent: (0, sinon_1.stub)(),
buttonComponent: (0, sinon_1.stub)()
};
var propsWithAuthPlugin = __assign({ authPlugins: [plugin] }, basicProps);
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, __assign({}, propsWithAuthPlugin)));
(0, chai_1.expect)(plugin.lookForCredentials.callCount).to.equal(1);
(0, chai_1.expect)(wrapper.state().authError).to.equal("error!");
});
it("shows error message if there's an auth error in the state", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
wrapper.setState({ authError: "error!" });
var error = wrapper.find(ErrorMessage_1.default);
(0, chai_1.expect)(error.length).to.equal(1);
(0, chai_1.expect)(error.props().message).to.equal("error!");
error.props().close();
(0, chai_1.expect)(wrapper.state().authError).to.be.null;
});
it("fetches a collection url when updated", function () {
var elem = document.createElement("div");
var collectionUrl = "http://feedbooks.github.io/opds-test-catalog/catalog/acquisition/blocks.xml";
var newCollection = "new collection url";
var setCollectionAndBook = (0, sinon_1.stub)().returns(setCollectionAndBookPromise);
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionUrl: collectionUrl, setCollectionAndBook: setCollectionAndBook }));
wrapper.setProps({
collectionUrl: newCollection
});
(0, chai_1.expect)(setCollectionAndBook.callCount).to.equal(2);
(0, chai_1.expect)(setCollectionAndBook.args[1][0]).to.equal(newCollection);
(0, chai_1.expect)(setCollectionAndBook.args[1][1]).not.to.be.ok;
});
it("shows loading message", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, isFetchingCollection: true }));
var loadings = wrapper.find(LoadingIndicator_1.default);
(0, chai_1.expect)(loadings.length).to.equal(1);
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, isFetchingBook: true }));
loadings = wrapper.find(LoadingIndicator_1.default);
(0, chai_1.expect)(loadings.length).to.equal(1);
});
it("shows error message", function () {
var fetchError = {
status: 500,
response: "test error",
url: "test error url"
};
var retry = (0, sinon_1.stub)();
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, error: fetchError, retryCollectionAndBook: retry }));
var error = wrapper.find(ErrorMessage_1.default);
(0, chai_1.expect)(error.props().message).to.contain(fetchError.url);
(0, chai_1.expect)(error.props().message).to.contain(fetchError.response);
(0, chai_1.expect)(error.props().retry).to.equal(retry);
});
it("shows auth provider selection form", function () {
var auth = {
showForm: true,
credentials: { provider: "test", credentials: "gibberish" },
title: "Super Classified Archive",
providers: [],
error: "Invalid Clearance ID and/or Access Key",
attemptedProvider: "Archive Login",
callback: (0, sinon_1.stub)(),
cancel: (0, sinon_1.stub)()
};
var saveAuthCredentials = (0, sinon_1.stub)();
var closeErrorAndHideAuthForm = (0, sinon_1.stub)();
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, auth: auth, saveAuthCredentials: saveAuthCredentials, closeErrorAndHideAuthForm: closeErrorAndHideAuthForm }));
var form = wrapper.find(AuthProviderSelectionForm_1.default);
var _a = form.props(), saveCredentials = _a.saveCredentials, hide = _a.hide, callback = _a.callback, cancel = _a.cancel, title = _a.title, error = _a.error, attemptedProvider = _a.attemptedProvider, providers = _a.providers;
(0, chai_1.expect)(saveCredentials).to.equal(saveAuthCredentials);
(0, chai_1.expect)(hide).to.equal(closeErrorAndHideAuthForm);
(0, chai_1.expect)(callback).to.equal(auth.callback);
(0, chai_1.expect)(cancel).to.equal(auth.cancel);
(0, chai_1.expect)(title).to.equal(auth.title);
(0, chai_1.expect)(providers).to.deep.equal(auth.providers);
(0, chai_1.expect)(error).to.equal(auth.error);
(0, chai_1.expect)(attemptedProvider).to.equal(auth.attemptedProvider);
});
it("shows book detail", function () {
var bookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
var loans = [
Object.assign({}, bookData, {
availability: { status: "available" }
})
];
var updateBook = (0, sinon_1.stub)();
var fulfillBook = (0, sinon_1.stub)();
var indirectFulfillBook = (0, sinon_1.stub)();
var epubReaderUrlTemplate = (0, sinon_1.stub)();
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { bookData: bookData, loans: loans, updateBook: updateBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, isSignedIn: true, epubReaderUrlTemplate: epubReaderUrlTemplate, setPreference: setPreference }));
var bookWrapper = wrapper.find(".book-details-wrapper");
var book = wrapper.find(BookDetails_1.default);
(0, chai_1.expect)(bookWrapper.length).to.equal(1);
(0, chai_1.expect)(book.props().book).to.equal(loans[0]);
(0, chai_1.expect)(book.props().updateBook).to.equal(updateBook);
(0, chai_1.expect)(book.props().isSignedIn).to.equal(true);
(0, chai_1.expect)(book.props().epubReaderUrlTemplate).to.equal(epubReaderUrlTemplate);
});
it("shows breadcrumbs", function () {
var history = [
{
id: "2nd id",
text: "2nd title",
url: "2nd url"
},
{
id: "last id",
text: "last title",
url: "last url"
}
];
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionData: collectionData_1.ungroupedCollectionData, history: history }));
var breadcrumbs = wrapper.find(Breadcrumbs_1.default);
var links = history.concat([
{
url: collectionData_1.ungroupedCollectionData.url,
text: collectionData_1.ungroupedCollectionData.title
}
]);
(0, chai_1.expect)(breadcrumbs.props().links).to.deep.equal(links);
});
it("uses custom computeBreadcrumbs function", function () {
var breadcrumb = {
url: "breacrumb url",
text: "breadcrumb text"
};
var computeBreadcrumbs = function (data) { return [breadcrumb]; };
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference, collectionData: collectionData_1.ungroupedCollectionData, computeBreadcrumbs: computeBreadcrumbs }));
var breadcrumbs = wrapper.find(Breadcrumbs_1.default);
(0, chai_1.expect)(breadcrumbs.props().links).to.deep.equal([breadcrumb]);
});
describe("provided a BookDetailsContainer", function () {
var Container = /** @class */ (function (_super) {
__extends(Container, _super);
function Container() {
return _super !== null && _super.apply(this, arguments) || this;
}
Container.prototype.render = function () {
return React.createElement("div", { className: "container" }, this.props.children);
};
return Container;
}(React.Component));
it("renders BookDetailsContainer with urls, refresh, and book details", function () {
var bookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
var refresh = (0, sinon_1.stub)();
var updateBook = (0, sinon_1.stub)();
var fulfillBook = (0, sinon_1.stub)();
var epubReaderUrlTemplate = (0, sinon_1.stub)();
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { bookData: bookData, bookUrl: bookData.url, collectionUrl: "test collection", refreshCollectionAndBook: refresh, setCollectionAndBook: mockSetCollectionAndBook, BookDetailsContainer: Container, updateBook: updateBook, fulfillBook: fulfillBook, epubReaderUrlTemplate: epubReaderUrlTemplate, setPreference: setPreference, indirectFulfillBook: indirectFulfillBook }));
var container = wrapper.find(Container);
var child = container.children().first();
(0, chai_1.expect)(container.props().bookUrl).to.equal(bookData.url);
(0, chai_1.expect)(container.props().collectionUrl).to.equal("test collection");
(0, chai_1.expect)(container.props().refreshCatalog).to.equal(refresh);
(0, chai_1.expect)(container.props().book).to.equal(bookData);
(0, chai_1.expect)(child.type()).to.equal(BookDetails_1.default);
(0, chai_1.expect)(child.props().book).to.equal(bookData);
(0, chai_1.expect)(child.props().epubReaderUrlTemplate).to.equal(epubReaderUrlTemplate);
});
it("does not render BookDetailsContainer if bookUrl and bookData.url are missing", function () {
var bookData = Object.assign({}, collectionData_1.groupedCollectionData.lanes[0].books[0], { url: null });
var refresh = (0, sinon_1.stub)();
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { bookData: bookData, bookUrl: undefined, collectionUrl: "test collection", refreshCollectionAndBook: refresh, setCollectionAndBook: mockSetCollectionAndBook, BookDetailsContainer: Container, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var containers = wrapper.find(Container);
(0, chai_1.expect)(containers.length).to.equal(0);
});
});
it("sets page title after updating", function () {
var elem = document.createElement("div");
var collectionData = collectionData_1.ungroupedCollectionData;
var bookData = collectionData.books[0];
var pageTitleTemplate = (0, sinon_1.spy)(function (collectionTitle, bookTitle) {
return "testing " + collectionTitle + ", " + bookTitle;
});
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData, bookData: bookData, pageTitleTemplate: pageTitleTemplate, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
// template should be invoked by componentWillMount
(0, chai_1.expect)(pageTitleTemplate.callCount).to.equal(1);
(0, chai_1.expect)(pageTitleTemplate.args[0][0]).to.equal(collectionData.title);
(0, chai_1.expect)(pageTitleTemplate.args[0][1]).to.equal(bookData.title);
(0, chai_1.expect)(document.title).to.equal("testing " + collectionData.title + ", " + bookData.title);
wrapper.setProps({
collectionData: null,
bookData: null,
pageTitleTemplate: pageTitleTemplate
});
// template should be invoked again by componentWillUpdate
(0, chai_1.expect)(pageTitleTemplate.callCount).to.equal(2);
(0, chai_1.expect)(pageTitleTemplate.args[1][0]).to.equal(null);
(0, chai_1.expect)(pageTitleTemplate.args[1][1]).to.equal(null);
(0, chai_1.expect)(document.title).to.equal("testing null, null");
});
describe("when given a header component", function () {
var wrapper;
var collectionData = Object.assign({}, collectionData_1.ungroupedCollectionData, {
search: {
url: "test search url",
searchData: {
description: "description",
shortName: "shortName",
template: function (s) { return s; }
}
}
});
var bookData = collectionData_1.ungroupedCollectionData.books[0];
var fetchLoans;
var clearAuthCredentials;
var Header = /** @class */ (function (_super) {
__extends(Header, _super);
function Header() {
return _super !== null && _super.apply(this, arguments) || this;
}
Header.prototype.render = function () {
return (React.createElement("div", { className: "header" },
this.props.children,
React.createElement(CatalogLink_1.default, { collectionUrl: "test url" }, "test")));
};
return Header;
}(React.Component));
beforeEach(function () {
fetchLoans = (0, sinon_1.stub)();
clearAuthCredentials = (0, sinon_1.stub)();
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { Header: Header, collectionData: collectionData, bookData: bookData, fetchSearchDescription: function (url) { }, fetchLoans: fetchLoans, clearAuthCredentials: clearAuthCredentials, isSignedIn: true, loansUrl: "loans", fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
});
it("renders the header", function () {
var header = wrapper.find(Header);
var search = header.childAt(0);
(0, chai_1.expect)(header.props().collectionTitle).to.equal(collectionData.title);
(0, chai_1.expect)(header.props().bookTitle).to.equal(bookData.title);
(0, chai_1.expect)(header.props().isSignedIn).to.equal(true);
(0, chai_1.expect)(header.props().fetchLoans).to.equal(fetchLoans);
(0, chai_1.expect)(header.props().clearAuthCredentials).to.equal(clearAuthCredentials);
(0, chai_1.expect)(header.props().loansUrl).to.equal("loans");
(0, chai_1.expect)(search.type()).to.equal(Search_1.default);
});
});
describe("when given a footer component", function () {
var wrapper;
var collectionData = collectionData_1.ungroupedCollectionData;
var bookData = collectionData_1.ungroupedCollectionData.books[0];
var Footer = /** @class */ (function (_super) {
__extends(Footer, _super);
function Footer() {
return _super !== null && _super.apply(this, arguments) || this;
}
Footer.prototype.render = function () {
return React.createElement("div", { className: "footer" });
};
return Footer;
}(React.Component));
beforeEach(function () {
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { Footer: Footer, collectionData: collectionData, bookData: bookData, fetchSearchDescription: function (url) { }, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
});
it("renders the footer", function () {
var footer = wrapper.find("footer");
(0, chai_1.expect)(footer.length).to.equal(1);
var footerComponent = footer.childAt(0);
(0, chai_1.expect)(footerComponent.props().collection).to.equal(collectionData);
});
});
describe("showNextBook()", function () {
var mockPush;
var context;
var collectionData;
var bookData;
var nextBookData;
var prevBookData;
var wrapper;
beforeEach(function () {
mockPush = (0, sinon_1.stub)();
context = (0, routing_1.mockRouterContext)(mockPush);
collectionData = collectionData_1.groupedCollectionData;
});
it("navigates to second book if currently showing first book", function () {
bookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
nextBookData = collectionData_1.groupedCollectionData.lanes[0].books[1];
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData, bookData: bookData, setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }), { context: context });
wrapper.instance().showNextBook();
(0, chai_1.expect)(mockPush.callCount).to.equal(1);
(0, chai_1.expect)(mockPush.args[0][0]).to.equal(context.pathFor(collectionData.url, nextBookData.url));
});
it("navigates to first book if currently showing last book", function () {
var lastIndex = collectionData_1.groupedCollectionData.lanes[0].books.length - 1;
bookData = collectionData_1.groupedCollectionData.lanes[0].books[lastIndex];
nextBookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData, bookData: bookData, setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }), { context: context });
wrapper.instance().showNextBook();
(0, chai_1.expect)(mockPush.callCount).to.equal(1);
(0, chai_1.expect)(mockPush.args[0][0]).to.equal(context.pathFor(collectionData.url, nextBookData.url));
});
});
describe("showPrevBook()", function () {
var mockPush;
var context;
var collectionData;
var bookData;
var nextBookData;
var prevBookData;
var wrapper;
beforeEach(function () {
mockPush = (0, sinon_1.stub)();
context = (0, routing_1.mockRouterContext)(mockPush);
collectionData = collectionData_1.groupedCollectionData;
});
it("navigates to last book if currently showing first book", function () {
var lastIndex = collectionData_1.groupedCollectionData.lanes[0].books.length - 1;
bookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
prevBookData = collectionData_1.groupedCollectionData.lanes[0].books[lastIndex];
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData, bookData: bookData, setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }), { context: context });
wrapper.instance().showPrevBook();
(0, chai_1.expect)(mockPush.callCount).to.equal(1);
(0, chai_1.expect)(mockPush.args[0][0]).to.equal(context.pathFor(collectionData.url, prevBookData.url));
});
it("navigates to first book if currently showing second book", function () {
bookData = collectionData_1.groupedCollectionData.lanes[0].books[1];
prevBookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData, bookData: bookData, setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }), { context: context });
wrapper.instance().showPrevBook();
(0, chai_1.expect)(mockPush.callCount).to.equal(1);
(0, chai_1.expect)(mockPush.args[0][0]).to.equal(context.pathFor(collectionData.url, prevBookData.url));
});
});
describe("routing", function () {
var store;
var collectionData = collectionData_1.groupedCollectionData;
var bookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
var push, context, childContextTypes;
var wrapper, root;
var history;
beforeEach(function () {
push = (0, sinon_1.stub)();
context = (0, routing_1.mockRouterContext)(push);
childContextTypes = {
router: PropTypes.object.isRequired,
pathFor: PropTypes.func.isRequired
};
history = [
{
text: "root title",
url: "root url"
},
{
text: "some title",
url: "some url"
}
];
wrapper = (0, enzyme_1.mount)(React.createElement(Root_1.Root, { collectionData: collectionData, bookData: undefined, history: history, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }), { context: context, childContextTypes: childContextTypes });
});
it("uses router to show a collection", function () {
var collectionLink = wrapper.find(".lane .title").first();
var collectionUrl = collectionData.lanes[0].url;
collectionLink.simulate("click", { button: 0 });
(0, chai_1.expect)(push.callCount).to.equal(1);
(0, chai_1.expect)(push.args[0][0]).to.equal(context.pathFor(collectionUrl, null));
});
it("uses router to show a book", function () {
var bookLink = wrapper.find(".book a").first();
var collectionUrl = collectionData.url;
var bookUrl = collectionData.lanes[0].books[0].url;
bookLink.simulate("click", { button: 0 });
(0, chai_1.expect)(push.callCount).to.equal(1);
(0, chai_1.expect)(push.args[0][0]).to.equal(context.pathFor(collectionUrl, bookUrl));
});
it("uses router to hide a book", function () {
wrapper.setProps({ bookData: bookData });
var collectionLink = wrapper
.find("ol.breadcrumbs")
.find(CatalogLink_1.default)
.last();
var collectionUrl = collectionData.url;
collectionLink.simulate("click", { button: 0 });
(0, chai_1.expect)(push.callCount).to.equal(1);
(0, chai_1.expect)(push.args[0][0]).to.equal(context.pathFor(collectionUrl, null));
});
});
describe("provided a CollectionContainer", function () {
var Tabs = /** @class */ (function (_super) {
__extends(Tabs, _super);
function Tabs() {
return _super !== null && _super.apply(this, arguments) || this;
}
Tabs.prototype.render = function () {
return React.createElement("div", { className: "tabs-container" });
};
return Tabs;
}(React.Component));
describe("No CollectionContainer component rendering", function () {
var history = [
{
id: "2nd id",
text: "2nd title",
url: "2nd url"
},
{
id: "last id",
text: "last title",
url: "last url"
}
];
it("should not render CollectionContainer if the component is not passed in", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData_1.ungroupedCollectionData, history: history, collectionUrl: "/test", setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var container = wrapper.find(Tabs);
(0, chai_1.expect)(container.length).to.equal(0);
});
it("should not render CollectionContainer if there is no collection data", function () {
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { history: history, collectionUrl: "/test", setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var container = wrapper.find(Tabs);
(0, chai_1.expect)(container.length).to.equal(0);
});
it("should not render CollectionContainer if the component is passed, but a book is being displayed", function () {
var bookData = collectionData_1.groupedCollectionData.lanes[0].books[0];
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { bookData: bookData, CollectionContainer: Tabs, collectionData: collectionData_1.ungroupedCollectionData, history: history, collectionUrl: "/test", setCollectionAndBook: mockSetCollectionAndBook, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var container = wrapper.find(Tabs);
(0, chai_1.expect)(container.length).to.equal(0);
});
});
it("renders CollectionContainer", function () {
var history = [
{
id: "2nd id",
text: "2nd title",
url: "2nd url"
},
{
id: "last id",
text: "last title",
url: "last url"
}
];
var facetGroups = [
{
facets: [
{
label: "eBooks",
href: "http://circulation.librarysimplified.org/groups/?entrypoint=Book",
active: false
},
{
label: "Audiobooks",
href: "http://circulation.librarysimplified.org/groups/?entrypoint=Audio",
active: false
}
],
label: "Formats"
}
];
collectionData_1.ungroupedCollectionData.facetGroups = facetGroups;
var wrapper = (0, enzyme_1.shallow)(React.createElement(Root_1.Root, { collectionData: collectionData_1.ungroupedCollectionData, history: history, collectionUrl: "/test", setCollectionAndBook: mockSetCollectionAndBook, CollectionContainer: Tabs, fulfillBook: fulfillBook, indirectFulfillBook: indirectFulfillBook, updateBook: updateBook, setPreference: setPreference }));
var container = wrapper.find(Tabs);
(0, chai_1.expect)(container.length).to.equal(1);
});
});
});