Niedzielski has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/387234 )

Change subject: Chore: split out summary unmarshaller
......................................................................

Chore: split out summary unmarshaller

Split out page summary unmarshalling responsibilities from page
unmarshalling.

Change-Id: I771a4891297ca2edccfc3057bdef4500311a2f42
---
M src/common/http/page-summary-http-client.ts
A src/common/marshallers/page-base-unmarshaller.test.ts
A src/common/marshallers/page-base-unmarshaller.ts
A src/common/marshallers/page-summary-unmarshaller.test.ts
A src/common/marshallers/page-summary-unmarshaller.ts
M src/common/marshallers/page-unmarshaller.test.ts
M src/common/marshallers/page-unmarshaller.ts
A src/common/marshallers/utils.test.ts
8 files changed, 308 insertions(+), 270 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/marvin refs/changes/34/387234/1

diff --git a/src/common/http/page-summary-http-client.ts 
b/src/common/http/page-summary-http-client.ts
index a223344..e18f0a7 100644
--- a/src/common/http/page-summary-http-client.ts
+++ b/src/common/http/page-summary-http-client.ts
@@ -2,7 +2,7 @@
 import { PageSummary } from "../models/page/summary";
 import { PageTitlePath } from "../models/page/title";
 import { RESTBase } from "../marshallers/restbase";
-import { unmarshalPageSummary } from "../marshallers/page-unmarshaller";
+import { unmarshalPageSummary } from 
"../marshallers/page-summary-unmarshaller";
 import HttpResponse from "./http-response";
 import { PageRedirect } from "./page-redirect";
 import reencodeRESTBaseTitlePath from "./restbase-title-encoder";
diff --git a/src/common/marshallers/page-base-unmarshaller.test.ts 
b/src/common/marshallers/page-base-unmarshaller.test.ts
new file mode 100644
index 0000000..9a7ac64
--- /dev/null
+++ b/src/common/marshallers/page-base-unmarshaller.test.ts
@@ -0,0 +1,28 @@
+import * as assert from "assert";
+import { PageGeolocation } from "../models/page/geolocation";
+import {
+  unmarshalETag,
+  unmarshalPageGeolocation
+} from "./page-base-unmarshaller";
+import { RESTBase } from "./restbase";
+import { EXPECTED_ETAG, HEADERS } from "./utils.test";
+
+describe("page-base-unmarshaller", () => {
+  it(".unmarshalPageGeolocation() unmarshals", () => {
+    const json: RESTBase.PageSummary.Geolocation = {
+      lat: 1,
+      lon: 2
+    };
+    const expected: PageGeolocation = {
+      latitude: 1,
+      longitude: 2
+    };
+    const result = unmarshalPageGeolocation(json as {});
+    assert.deepStrictEqual(result, expected);
+  });
+
+  it(".unmarshalETag() unmarshals", () => {
+    const result = unmarshalETag(HEADERS);
+    assert.deepStrictEqual(result, EXPECTED_ETAG);
+  });
+});
diff --git a/src/common/marshallers/page-base-unmarshaller.ts 
b/src/common/marshallers/page-base-unmarshaller.ts
new file mode 100644
index 0000000..b87c104
--- /dev/null
+++ b/src/common/marshallers/page-base-unmarshaller.ts
@@ -0,0 +1,33 @@
+import { ETag } from "../models/etag";
+import { PageGeolocation } from "../models/page/geolocation";
+import { PageTitleID } from "../models/page/title";
+import { IsomorphicHeaders } from "../types/isomorphic-unfetch-extras";
+import { JSONObject } from "../types/json";
+import { RESTBase } from "./restbase";
+
+export function unmarshalPageTitleID(url: string): PageTitleID {
+  // Titles themselves may contain slashes, however, RESTBase only understands
+  // titles with encoded slashes so when this unmarshaller encounters a slash 
it
+  // may safely consider this a path segment and not part of the title.
+  const titlePath = url.split("/").pop();
+  if (titlePath === undefined) {
+    throw new Error("titlePath should be known at response time.");
+  }
+  return decodeURI(titlePath);
+}
+
+export const unmarshalPageGeolocation = (json: JSONObject): PageGeolocation => 
{
+  if (json.latitude) {
+    const type: RESTBase.PageSections.Geolocation = json as any;
+    return { latitude: type.latitude, longitude: type.longitude };
+  } else {
+    const type: RESTBase.PageSummary.Geolocation = json as any;
+    return { latitude: type.lat, longitude: type.lon };
+  }
+};
+
+export const unmarshalETag = (headers: IsomorphicHeaders): ETag => {
+  const etag = headers.get("ETag") as string;
+  const [revision, timeID] = etag.split("/");
+  return { revision: parseInt(revision, 10), timeID };
+};
diff --git a/src/common/marshallers/page-summary-unmarshaller.test.ts 
b/src/common/marshallers/page-summary-unmarshaller.test.ts
new file mode 100644
index 0000000..c0abf50
--- /dev/null
+++ b/src/common/marshallers/page-summary-unmarshaller.test.ts
@@ -0,0 +1,111 @@
+import * as assert from "assert";
+import { PageSummary, pageSummaryReviver } from "../models/page/summary";
+import { PageImage, PageThumbnail } from "../models/page/image";
+import {
+  unmarshalPageImage,
+  unmarshalPageThumbnail,
+  unmarshalPageSummary
+} from "./page-summary-unmarshaller";
+import { RESTBase } from "./restbase";
+import { EXPECTED_ETAG, HEADERS, reviveFile } from "./utils.test";
+
+const NOW = new Date(Date.now()).toString();
+
+describe("page-summary-unmarshaller", () => {
+  describe(".unmarshalPageThumbnail()", () => {
+    [false, true].forEach(landscape => {
+      it(`unmarshals ${landscape ? "landscape" : "portrait"}`, () => {
+        const width = landscape ? 2 : 1;
+        const height = landscape ? 1 : 2;
+        const json: RESTBase.PageSummary.Thumbnail = {
+          source: "source",
+          original: "original",
+          width,
+          height
+        };
+        const expected: PageThumbnail = {
+          url: "source",
+          width,
+          height,
+          landscape,
+          originalURL: "original"
+        };
+        const result = unmarshalPageThumbnail(json as {});
+        assert.deepStrictEqual(result, expected);
+      });
+    });
+  });
+
+  describe(".unmarshalPageImage()", () => {
+    [false, true].forEach(landscape => {
+      it(`unmarshals ${landscape ? "landscape" : "portrait"}`, () => {
+        const width = landscape ? 2 : 1;
+        const height = landscape ? 1 : 2;
+        const json: RESTBase.PageSummary.Image = {
+          source: "source",
+          width,
+          height
+        };
+        const expected: PageImage = {
+          url: "source",
+          width,
+          height,
+          landscape
+        };
+        const result = unmarshalPageImage(json as {});
+        assert.deepStrictEqual(result, expected);
+      });
+    });
+  });
+
+  describe(".unmarshalPageSummary()", () => {
+    // eslint-disable-next-line max-len
+    it("unmarshals omitting undefined properties and returns extract even when 
there are no paragraphs", () => {
+      const json: RESTBase.PageSummary.PageSummary = {
+        title: "title",
+        displaytitle: "displaytitle",
+        pageid: 1,
+        extract: "extract",
+        extract_html: "extract_html",
+        lang: "en",
+        dir: "ltr",
+        timestamp: NOW,
+        description: "description"
+      };
+      const expected: PageSummary = {
+        pageID: 1,
+        titleID: "titleID",
+        titleText: "title",
+        titleHTML: "displaytitle",
+        descriptionText: "description",
+        lastModified: new Date(Date.parse(NOW)),
+        etag: EXPECTED_ETAG,
+        wikiLanguageCode: "en",
+        localeDirection: "ltr",
+        extractText: "extract",
+        extractHTML: ["extract_html"]
+      };
+      const result = unmarshalPageSummary({
+        url: "titleID",
+        headers: HEADERS,
+        json: json as {}
+      });
+      assert.deepStrictEqual(result, expected);
+    });
+
+    it("unmarshals a server response", () => {
+      const json = require("./page-summary-restbase.test.json");
+      const result = unmarshalPageSummary({
+        requestTitleID: "mount_everest",
+        url: "https://en.wikipedia.org/api/rest_v1/page/summary/Mount_Everest";,
+        headers: HEADERS,
+        json
+      });
+      const expected = reviveFile(
+        "./page-summary-expected.test.json",
+        pageSummaryReviver
+      );
+      assert.deepStrictEqual(result, expected);
+    });
+  });
+});
diff --git a/src/common/marshallers/page-summary-unmarshaller.ts 
b/src/common/marshallers/page-summary-unmarshaller.ts
new file mode 100644
index 0000000..2b2b206
--- /dev/null
+++ b/src/common/marshallers/page-summary-unmarshaller.ts
@@ -0,0 +1,110 @@
+import { PageImage, PageThumbnail } from "../models/page/image";
+import { PageSummary } from "../models/page/summary";
+import { PageTitleID } from "../models/page/title";
+import { IsomorphicHeaders } from "../types/isomorphic-unfetch-extras";
+import { JSONObject } from "../types/json";
+import {
+  unmarshalPageTitleID,
+  unmarshalPageGeolocation,
+  unmarshalETag
+} from "./page-base-unmarshaller";
+import { RESTBase } from "./restbase";
+
+export const unmarshalPageThumbnail = (json: JSONObject): PageThumbnail => {
+  const type: RESTBase.PageSummary.Thumbnail = json as any;
+  return {
+    url: type.source,
+    originalURL: type.original,
+    width: type.width,
+    height: type.height,
+    landscape: type.width > type.height
+  };
+};
+
+export const unmarshalPageImage = (json: JSONObject): PageImage => {
+  const type: RESTBase.PageSummary.Image = json as any;
+  return {
+    url: type.source,
+    width: type.width,
+    height: type.height,
+    landscape: type.width > type.height
+  };
+};
+
+// todo: remove this function and Domino package from package*.json, the
+//       corresponding Webpack IgnorePlugin, and the Domino typing, when
+//       isomorphic HTML parsing is unneeded. Some other options explored:
+// - undom advertises itself as "DOM but not a parser". Parsing, serialization,
+//   and selectors are all unsupported. There is a recipe for rudimentary
+//   serialization but the real issue is the lack of a parser which is 
essential
+//   to Marvin's use case. The GitHub issues have several discussions of an
+//   extensible plugin system that may help fill in these gaps but to date 
these
+//   features are unavailable.
+// - This parsing logic could live in the Preact components render cycle but:
+//   - Rendering in a component will still require a DOM on the server.
+//   - The expected place to receive this data is at unmarshalling time.
+// - Only Domino was considered. jsdom and other alternatives were not 
explored.
+// - A new Marvin service endpoint gives the project a great deal of 
flexibility
+//   in how it handles server responses. However, it comes at the great expense
+//   of increased complexity and reduced performance:
+//   - Marvin already offers client and server code. Adding a service API is a
+//     refactor that decreases code clarity.
+//   - Requests from the server and the client must be issued to Marvin then
+//     reissued to the real data endpoints.
+//   - Example implementation: https://gerrit.wikimedia.org/r/#/c/379698/4.
+// Domino was chosen for familiarity and because it's already used on the MCS
+// backend. This is a service-only dependency so the client filesize is not
+// affected at the expense of two different code paths.
+const parseExtractHTML = (extractHTML: string) => {
+  const element =
+    typeof document === "undefined"
+      ? require("domino").createDocument().body
+      : document.implementation.createHTMLDocument("").body;
+  element.innerHTML = extractHTML;
+
+  const paragraphs = Array.from(element.querySelectorAll("p"));
+  return paragraphs.length
+    ? paragraphs.map((paragraph: HTMLParagraphElement) => paragraph.outerHTML)
+    : [extractHTML];
+};
+
+export const unmarshalPageSummary = ({
+  url,
+  requestTitleID,
+  headers,
+  json
+}: {
+  url: string;
+  requestTitleID?: PageTitleID | string;
+  headers: IsomorphicHeaders;
+  json: JSONObject;
+}): PageSummary => {
+  const type: RESTBase.PageSummary.PageSummary = json as any;
+  const result: PageSummary = {
+    pageID: type.pageid,
+    titleID: unmarshalPageTitleID(url),
+    titleText: type.title,
+    titleHTML: type.displaytitle,
+    lastModified: new Date(type.timestamp),
+    descriptionText: type.description,
+    etag: unmarshalETag(headers),
+
+    wikiLanguageCode: type.lang,
+    localeDirection: type.dir,
+    extractText: type.extract,
+    extractHTML: parseExtractHTML(type.extract_html)
+  };
+  if (requestTitleID !== undefined) {
+    result.requestTitleID = requestTitleID;
+  }
+  if (type.coordinates) {
+    result.geolocation = unmarshalPageGeolocation(type.coordinates as {});
+  }
+  if (type.thumbnail) {
+    result.thumbnail = unmarshalPageThumbnail(type.thumbnail as {});
+  }
+  if (type.originalimage) {
+    result.image = unmarshalPageImage(type.originalimage as {});
+  }
+  return result;
+};
diff --git a/src/common/marshallers/page-unmarshaller.test.ts 
b/src/common/marshallers/page-unmarshaller.test.ts
index 9904460..2e54284 100644
--- a/src/common/marshallers/page-unmarshaller.test.ts
+++ b/src/common/marshallers/page-unmarshaller.test.ts
@@ -1,9 +1,6 @@
 import * as assert from "assert";
-import * as fetch from "node-fetch";
-import { JSONValue } from "../types/json";
-import { PageSummary, pageSummaryReviver } from "../models/page/summary";
-import { PageImage, PageThumbnail } from "../models/page/image";
-import { PageGeolocation } from "../models/page/geolocation";
+
+import { PageImage } from "../models/page/image";
 import { PageNamespace } from "../models/page/namespace";
 import {
   Page,
@@ -15,82 +12,21 @@
 } from "../models/page/page";
 import { PageUser, PageUserGender } from "../models/page/user";
 import {
-  unmarshalETag,
   unmarshalPage,
   unmarshalPageLead,
   unmarshalPageBody,
-  unmarshalPageGeolocation,
-  unmarshalPageImage,
   unmarshalPageImageMap,
-  unmarshalPageThumbnail,
   unmarshalPageSection,
   unmarshalPageSections,
-  unmarshalPageSummary,
   unmarshalPageUser,
   unmarshalPageUserGender
 } from "./page-unmarshaller";
 import { RESTBase } from "./restbase";
-
-const revive = (
-  filename: string,
-  reviver?: (key: any, value: JSONValue) => any
-) => JSON.parse(JSON.stringify(require(filename)), reviver);
+import { EXPECTED_ETAG, HEADERS, reviveFile } from "./utils.test";
 
 const NOW = new Date(Date.now()).toString();
 
-const ETAG_REVISION = 802006980;
-const ETAG_TIME_ID = "4f754377-a235-11e7-a776-efb84f18649a";
-const HEADERS = new fetch.Headers();
-HEADERS.append("etag", `${ETAG_REVISION}/${ETAG_TIME_ID}`);
-const EXPECTED_ETAG = { revision: ETAG_REVISION, timeID: ETAG_TIME_ID };
-
 describe("page-unmarshaller", () => {
-  describe(".unmarshalPageThumbnail()", () => {
-    [false, true].forEach(landscape => {
-      it(`unmarshals ${landscape ? "landscape" : "portrait"}`, () => {
-        const width = landscape ? 2 : 1;
-        const height = landscape ? 1 : 2;
-        const json: RESTBase.PageSummary.Thumbnail = {
-          source: "source",
-          original: "original",
-          width,
-          height
-        };
-        const expected: PageThumbnail = {
-          url: "source",
-          width,
-          height,
-          landscape,
-          originalURL: "original"
-        };
-        const result = unmarshalPageThumbnail(json as {});
-        assert.deepStrictEqual(result, expected);
-      });
-    });
-  });
-
-  describe(".unmarshalPageImage()", () => {
-    [false, true].forEach(landscape => {
-      it(`unmarshals ${landscape ? "landscape" : "portrait"}`, () => {
-        const width = landscape ? 2 : 1;
-        const height = landscape ? 1 : 2;
-        const json: RESTBase.PageSummary.Image = {
-          source: "source",
-          width,
-          height
-        };
-        const expected: PageImage = {
-          url: "source",
-          width,
-          height,
-          landscape
-        };
-        const result = unmarshalPageImage(json as {});
-        assert.deepStrictEqual(result, expected);
-      });
-    });
-  });
-
   describe(".unmarshalPageImageMap()", () => {
     it("unmarshals an empty map", () => {
       const json: RESTBase.PageSections.ThumbnailMap = {
@@ -112,75 +48,6 @@
         { url: "2", width: 2 }
       ];
       const result = unmarshalPageImageMap(json as {});
-      assert.deepStrictEqual(result, expected);
-    });
-  });
-
-  it(".unmarshalPageGeolocation() unmarshals", () => {
-    const json: RESTBase.PageSummary.Geolocation = {
-      lat: 1,
-      lon: 2
-    };
-    const expected: PageGeolocation = {
-      latitude: 1,
-      longitude: 2
-    };
-    const result = unmarshalPageGeolocation(json as {});
-    assert.deepStrictEqual(result, expected);
-  });
-
-  it(".unmarshalETag() unmarshals", () => {
-    const result = unmarshalETag(HEADERS);
-    assert.deepStrictEqual(result, EXPECTED_ETAG);
-  });
-
-  describe(".unmarshalPageSummary()", () => {
-    // eslint-disable-next-line max-len
-    it("unmarshals omitting undefined properties and returns extract even when 
there are no paragraphs", () => {
-      const json: RESTBase.PageSummary.PageSummary = {
-        title: "title",
-        displaytitle: "displaytitle",
-        pageid: 1,
-        extract: "extract",
-        extract_html: "extract_html",
-        lang: "en",
-        dir: "ltr",
-        timestamp: NOW,
-        description: "description"
-      };
-      const expected: PageSummary = {
-        pageID: 1,
-        titleID: "titleID",
-        titleText: "title",
-        titleHTML: "displaytitle",
-        descriptionText: "description",
-        lastModified: new Date(Date.parse(NOW)),
-        etag: EXPECTED_ETAG,
-        wikiLanguageCode: "en",
-        localeDirection: "ltr",
-        extractText: "extract",
-        extractHTML: ["extract_html"]
-      };
-      const result = unmarshalPageSummary({
-        url: "titleID",
-        headers: HEADERS,
-        json: json as {}
-      });
-      assert.deepStrictEqual(result, expected);
-    });
-
-    it("unmarshals a server response", () => {
-      const json = require("./page-summary-restbase.test.json");
-      const result = unmarshalPageSummary({
-        requestTitleID: "mount_everest",
-        url: "https://en.wikipedia.org/api/rest_v1/page/summary/Mount_Everest";,
-        headers: HEADERS,
-        json
-      });
-      const expected = revive(
-        "./page-summary-expected.test.json",
-        pageSummaryReviver
-      );
       assert.deepStrictEqual(result, expected);
     });
   });
@@ -353,7 +220,7 @@
         headers: HEADERS,
         json
       });
-      const expected = revive(
+      const expected = reviveFile(
         "./page-lead-expected.test.json",
         pageLeadReviver
       );
@@ -393,7 +260,7 @@
     it("unmarshals a server response", () => {
       const json = require("./page-body-restbase.test.json");
       const result = unmarshalPageBody(json);
-      const expected = revive("./page-body-expected.test.json");
+      const expected = reviveFile("./page-body-expected.test.json");
       assert.deepStrictEqual(result, expected);
     });
   });
@@ -455,7 +322,7 @@
         headers: HEADERS,
         json
       });
-      const expected = revive("./page-expected.test.json", pageReviver);
+      const expected = reviveFile("./page-expected.test.json", pageReviver);
       assert.deepStrictEqual(result, expected);
     });
   });
diff --git a/src/common/marshallers/page-unmarshaller.ts 
b/src/common/marshallers/page-unmarshaller.ts
index f088562..f19e859 100644
--- a/src/common/marshallers/page-unmarshaller.ts
+++ b/src/common/marshallers/page-unmarshaller.ts
@@ -1,34 +1,15 @@
-import { PageImage, PageThumbnail } from "../models/page/image";
-import { ETag } from "../models/etag";
-import { PageGeolocation } from "../models/page/geolocation";
-import { PageSummary } from "../models/page/summary";
+import { PageImage } from "../models/page/image";
 import { PageTitleID } from "../models/page/title";
 import { Page, PageLead, PageBody, PageSection } from "../models/page/page";
 import { PageUser, PageUserGender } from "../models/page/user";
 import { IsomorphicHeaders } from "../types/isomorphic-unfetch-extras";
 import { JSONArray, JSONObject } from "../types/json";
+import {
+  unmarshalPageTitleID,
+  unmarshalPageGeolocation,
+  unmarshalETag
+} from "./page-base-unmarshaller";
 import { RESTBase } from "./restbase";
-
-export const unmarshalPageThumbnail = (json: JSONObject): PageThumbnail => {
-  const type: RESTBase.PageSummary.Thumbnail = json as any;
-  return {
-    url: type.source,
-    originalURL: type.original,
-    width: type.width,
-    height: type.height,
-    landscape: type.width > type.height
-  };
-};
-
-export const unmarshalPageImage = (json: JSONObject): PageImage => {
-  const type: RESTBase.PageSummary.Image = json as any;
-  return {
-    url: type.source,
-    width: type.width,
-    height: type.height,
-    landscape: type.width > type.height
-  };
-};
 
 export const unmarshalPageImageMap = (json: JSONObject): PageImage[] => {
   const type: RESTBase.PageSections.ThumbnailMap = json as any;
@@ -38,111 +19,6 @@
       url: type.urls[width],
       width: parseInt(width, 10)
     }));
-};
-
-export const unmarshalPageGeolocation = (json: JSONObject): PageGeolocation => 
{
-  if (json.latitude) {
-    const type: RESTBase.PageSections.Geolocation = json as any;
-    return { latitude: type.latitude, longitude: type.longitude };
-  } else {
-    const type: RESTBase.PageSummary.Geolocation = json as any;
-    return { latitude: type.lat, longitude: type.lon };
-  }
-};
-
-// todo: remove this function and Domino package from package*.json, the
-//       corresponding Webpack IgnorePlugin, and the Domino typing, when
-//       isomorphic HTML parsing is unneeded. Some other options explored:
-// - undom advertises itself as "DOM but not a parser". Parsing, serialization,
-//   and selectors are all unsupported. There is a recipe for rudimentary
-//   serialization but the real issue is the lack of a parser which is 
essential
-//   to Marvin's use case. The GitHub issues have several discussions of an
-//   extensible plugin system that may help fill in these gaps but to date 
these
-//   features are unavailable.
-// - This parsing logic could live in the Preact components render cycle but:
-//   - Rendering in a component will still require a DOM on the server.
-//   - The expected place to receive this data is at unmarshalling time.
-// - Only Domino was considered. jsdom and other alternatives were not 
explored.
-// - A new Marvin service endpoint gives the project a great deal of 
flexibility
-//   in how it handles server responses. However, it comes at the great expense
-//   of increased complexity and reduced performance:
-//   - Marvin already offers client and server code. Adding a service API is a
-//     refactor that decreases code clarity.
-//   - Requests from the server and the client must be issued to Marvin then
-//     reissued to the real data endpoints.
-//   - Example implementation: https://gerrit.wikimedia.org/r/#/c/379698/4.
-// Domino was chosen for familiarity and because it's already used on the MCS
-// backend. This is a service-only dependency so the client filesize is not
-// affected at the expense of two different code paths.
-const parseExtractHTML = (extractHTML: string) => {
-  const element =
-    typeof document === "undefined"
-      ? require("domino").createDocument().body
-      : document.implementation.createHTMLDocument("").body;
-  element.innerHTML = extractHTML;
-
-  const paragraphs = Array.from(element.querySelectorAll("p"));
-  return paragraphs.length
-    ? paragraphs.map((paragraph: HTMLParagraphElement) => paragraph.outerHTML)
-    : [extractHTML];
-};
-
-export const unmarshalETag = (headers: IsomorphicHeaders): ETag => {
-  const etag = headers.get("ETag") as string;
-  const [revision, timeID] = etag.split("/");
-  return { revision: parseInt(revision, 10), timeID };
-};
-
-export function unmarshalPageTitleID(url: string): PageTitleID {
-  // Titles themselves may contain slashes, however, RESTBase only understands
-  // titles with encoded slashes so when this unmarshaller encounters a slash 
it
-  // may safely consider this a path segment and not part of the title.
-  const titlePath = url.split("/").pop();
-  if (titlePath === undefined) {
-    throw new Error("titlePath should be known at response time.");
-  }
-  return decodeURI(titlePath);
-}
-
-export const unmarshalPageSummary = ({
-  url,
-  requestTitleID,
-  headers,
-  json
-}: {
-  url: string;
-  requestTitleID?: PageTitleID | string;
-  headers: IsomorphicHeaders;
-  json: JSONObject;
-}): PageSummary => {
-  const type: RESTBase.PageSummary.PageSummary = json as any;
-  const result: PageSummary = {
-    pageID: type.pageid,
-    titleID: unmarshalPageTitleID(url),
-    titleText: type.title,
-    titleHTML: type.displaytitle,
-    lastModified: new Date(type.timestamp),
-    descriptionText: type.description,
-    etag: unmarshalETag(headers),
-
-    wikiLanguageCode: type.lang,
-    localeDirection: type.dir,
-    extractText: type.extract,
-    extractHTML: parseExtractHTML(type.extract_html)
-  };
-  if (requestTitleID !== undefined) {
-    result.requestTitleID = requestTitleID;
-  }
-  if (type.coordinates) {
-    result.geolocation = unmarshalPageGeolocation(type.coordinates as {});
-  }
-  if (type.thumbnail) {
-    result.thumbnail = unmarshalPageThumbnail(type.thumbnail as {});
-  }
-  if (type.originalimage) {
-    result.image = unmarshalPageImage(type.originalimage as {});
-  }
-  return result;
 };
 
 export const unmarshalPageUserGender = (json: string): PageUserGender => {
diff --git a/src/common/marshallers/utils.test.ts 
b/src/common/marshallers/utils.test.ts
new file mode 100644
index 0000000..9b35ebe
--- /dev/null
+++ b/src/common/marshallers/utils.test.ts
@@ -0,0 +1,13 @@
+import * as fetch from "node-fetch";
+import { JSONValue } from "../types/json";
+
+export const reviveFile = (
+  filename: string,
+  reviver?: (key: any, value: JSONValue) => any
+) => JSON.parse(JSON.stringify(require(filename)), reviver);
+
+const ETAG_REVISION = 802006980;
+const ETAG_TIME_ID = "4f754377-a235-11e7-a776-efb84f18649a";
+export const HEADERS = new fetch.Headers();
+HEADERS.append("etag", `${ETAG_REVISION}/${ETAG_TIME_ID}`);
+export const EXPECTED_ETAG = { revision: ETAG_REVISION, timeID: ETAG_TIME_ID };

-- 
To view, visit https://gerrit.wikimedia.org/r/387234
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I771a4891297ca2edccfc3057bdef4500311a2f42
Gerrit-PatchSet: 1
Gerrit-Project: marvin
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: Sniedzielski <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to