@@ -3,6 +3,7 @@ const sinon = require('sinon');
33const expect = require ( 'unexpected' ) . clone ( ) . use ( require ( 'unexpected-sinon' ) ) ;
44const subfont = require ( '../lib/subfont' ) ;
55const httpception = require ( 'httpception' ) ;
6+ const AssetGraph = require ( 'assetgraph' ) ;
67const proxyquire = require ( 'proxyquire' ) ;
78const pathModule = require ( 'path' ) ;
89const openSansBold = require ( 'fs' ) . readFileSync (
@@ -17,7 +18,11 @@ const openSansBold = require('fs').readFileSync(
1718describe ( 'subfont' , function ( ) {
1819 let mockConsole ;
1920 beforeEach ( async function ( ) {
20- mockConsole = { log : sinon . spy ( ) , error : sinon . spy ( ) } ;
21+ mockConsole = { log : sinon . spy ( ) , warn : sinon . spy ( ) , error : sinon . spy ( ) } ;
22+ } ) ;
23+
24+ afterEach ( function ( ) {
25+ sinon . restore ( ) ;
2126 } ) ;
2227
2328 describe ( 'when a font is referenced by a stylesheet hosted outside the root' , function ( ) {
@@ -212,6 +217,199 @@ describe('subfont', function () {
212217 } ) ;
213218 } ) ;
214219
220+ describe ( 'when fetching an entry point results in an HTTP redirect' , function ( ) {
221+ describe ( 'with a single entry point' , function ( ) {
222+ beforeEach ( function ( ) {
223+ httpception ( [
224+ {
225+ request : 'GET http://example.com/' ,
226+ response : {
227+ statusCode : 301 ,
228+ headers : {
229+ Location : 'https://somewhereelse.com/' ,
230+ } ,
231+ } ,
232+ } ,
233+ {
234+ request : 'GET https://somewhereelse.com/' ,
235+ response : {
236+ headers : {
237+ 'Content-Type' : 'text/html; charset=utf-8' ,
238+ } ,
239+ body : `<!DOCTYPE html>
240+ <html>
241+
242+ <head>
243+ <style>
244+ @font-face {
245+ font-family: Open Sans;
246+ src: url(OpenSans.woff) format('woff');
247+ }
248+
249+ div {
250+ font-family: Open Sans;
251+ }
252+ </style>
253+ </head>
254+ <body>
255+ <div>Hello</div>
256+ </body>
257+ </html>
258+ ` ,
259+ } ,
260+ } ,
261+ {
262+ request : 'GET http://somewhereelse.com/OpenSans.woff' ,
263+ response : {
264+ headers : {
265+ 'Content-Type' : 'font/woff' ,
266+ } ,
267+ body : openSansBold ,
268+ } ,
269+ } ,
270+ ] ) ;
271+ } ) ;
272+
273+ it ( 'should issue a warning' , async function ( ) {
274+ const root = 'http://example.com/' ;
275+ sinon . stub ( AssetGraph . prototype , 'info' ) ;
276+
277+ const assetGraph = await subfont (
278+ {
279+ root,
280+ inputFiles : [ root ] ,
281+ fallbacks : false ,
282+ silent : true ,
283+ dryRun : true ,
284+ } ,
285+ mockConsole
286+ ) ;
287+
288+ const htmlAssets = assetGraph . findAssets ( {
289+ isInitial : true ,
290+ type : 'Html' ,
291+ } ) ;
292+ expect ( htmlAssets , 'to have length' , 1 ) ;
293+ expect (
294+ htmlAssets [ 0 ] . url ,
295+ 'to equal' ,
296+ 'https://somewhereelse.com/index.html'
297+ ) ;
298+ expect ( assetGraph . info , 'to have a call satisfying' , ( ) => {
299+ assetGraph . info (
300+ new Error (
301+ 'http://example.com/ redirected to https://somewhereelse.com/'
302+ )
303+ ) ;
304+ } ) ;
305+ } ) ;
306+
307+ it ( 'should change the root of the graph so that files get written to disc' , async function ( ) {
308+ const root = 'http://example.com/' ;
309+
310+ sinon . stub ( AssetGraph . prototype , 'info' ) ;
311+ const assetGraph = await subfont (
312+ {
313+ root,
314+ inputFiles : [ root ] ,
315+ fallbacks : false ,
316+ silent : true ,
317+ dryRun : true ,
318+ } ,
319+ mockConsole
320+ ) ;
321+
322+ expect ( assetGraph . root , 'to equal' , 'https://somewhereelse.com/' ) ;
323+
324+ expect ( assetGraph . info , 'to have a call satisfying' , ( ) => {
325+ assetGraph . info (
326+ new Error (
327+ 'All entrypoints redirected, changing root from http://example.com/ to https://somewhereelse.com/'
328+ )
329+ ) ;
330+ } ) ;
331+ } ) ;
332+ } ) ;
333+
334+ describe ( 'but other entry points do not get redirected' , function ( ) {
335+ beforeEach ( function ( ) {
336+ httpception ( [
337+ {
338+ request : 'GET http://example.com/' ,
339+ response : {
340+ statusCode : 301 ,
341+ headers : {
342+ Location : 'https://somewhereelse.com/' ,
343+ } ,
344+ } ,
345+ } ,
346+ {
347+ request : 'GET http://example.com/page2' ,
348+ response : {
349+ headers : {
350+ 'Content-Type' : 'text/html; charset=utf-8' ,
351+ } ,
352+ body : `<!DOCTYPE html><html></html>` ,
353+ } ,
354+ } ,
355+ {
356+ request : 'GET https://somewhereelse.com/' ,
357+ response : {
358+ headers : {
359+ 'Content-Type' : 'text/html; charset=utf-8' ,
360+ } ,
361+ body : `<!DOCTYPE html>
362+ <html>
363+ <head>
364+ <style>
365+ @font-face {
366+ font-family: Open Sans;
367+ src: url(OpenSans.woff) format('woff');
368+ }
369+
370+ div {
371+ font-family: Open Sans;
372+ }
373+ </style>
374+ </head>
375+ <body>
376+ <div>Hello</div>
377+ </body>
378+ </html>
379+ ` ,
380+ } ,
381+ } ,
382+ {
383+ request : 'GET http://somewhereelse.com/OpenSans.woff' ,
384+ response : {
385+ headers : {
386+ 'Content-Type' : 'font/woff' ,
387+ } ,
388+ body : openSansBold ,
389+ } ,
390+ } ,
391+ ] ) ;
392+ } ) ;
393+
394+ it ( 'should not change the root' , async function ( ) {
395+ const root = 'http://example.com/' ;
396+
397+ const assetGraph = await subfont (
398+ {
399+ root,
400+ inputFiles : [ root , `${ root } page2` ] ,
401+ fallbacks : false ,
402+ silent : true ,
403+ dryRun : true ,
404+ } ,
405+ mockConsole
406+ ) ;
407+
408+ expect ( assetGraph . root , 'to equal' , 'http://example.com/' ) ;
409+ } ) ;
410+ } ) ;
411+ } ) ;
412+
215413 it ( 'should not dive into iframes' , async function ( ) {
216414 const root = encodeURI (
217415 `file://${ pathModule . resolve ( __dirname , '..' , 'testdata' , 'iframe' ) } `
0 commit comments