|
1 | 1 | import tap from 'tap';
|
2 | 2 | import { PodletServer, HttpServer, HttpsServer } from '@podium/test-utils';
|
3 | 3 | import { HttpIncoming } from '@podium/utils';
|
| 4 | +import Podlet from '@podium/podlet'; |
| 5 | +import express from 'express'; |
4 | 6 | import Client from '../lib/client.js';
|
5 | 7 |
|
6 | 8 | // Fake headers
|
@@ -562,3 +564,149 @@ tap.test(
|
562 | 564 | t.same(responseB.content, '<p>fallback</p>');
|
563 | 565 | },
|
564 | 566 | );
|
| 567 | + |
| 568 | +function createPodletServer() { |
| 569 | + const podlet = new Podlet({ |
| 570 | + name: 'foo', |
| 571 | + version: 'v1.0.0', |
| 572 | + pathname: '/', |
| 573 | + development: true, |
| 574 | + }); |
| 575 | + |
| 576 | + podlet.js({ |
| 577 | + value: '/scripts.js', |
| 578 | + type: 'module', |
| 579 | + async: true, |
| 580 | + data: [{ key: 'foo', value: 'bar' }], |
| 581 | + scope: 'content', |
| 582 | + }); |
| 583 | + podlet.css({ value: '/styles.css', scope: 'content' }); |
| 584 | + |
| 585 | + const app = express(); |
| 586 | + app.use(podlet.middleware()); |
| 587 | + app.get(podlet.manifest(), (req, res) => { |
| 588 | + res.send(podlet); |
| 589 | + }); |
| 590 | + app.get(podlet.content(), (req, res) => { |
| 591 | + res.sendHeaders(); |
| 592 | + setTimeout(() => { |
| 593 | + res.podiumSend('<h1>OK!</h1>'); |
| 594 | + }, 1000); |
| 595 | + }); |
| 596 | + return app; |
| 597 | +} |
| 598 | + |
| 599 | +tap.test( |
| 600 | + 'assets - .js() and .css() - Link headers - should be used to send assets', |
| 601 | + async (t) => { |
| 602 | + const app = createPodletServer(); |
| 603 | + const server = app.listen(0); |
| 604 | + |
| 605 | + const result = await fetch( |
| 606 | + `http://localhost:${server.address().port}/`, |
| 607 | + ); |
| 608 | + const linkHeaders = result.headers.get('link'); |
| 609 | + |
| 610 | + t.equal( |
| 611 | + linkHeaders, |
| 612 | + '</scripts.js>; async=true; type=module; data-foo=bar; scope=content; asset-type=script, </styles.css>; type=text/css; rel=stylesheet; scope=content; asset-type=style', |
| 613 | + ); |
| 614 | + |
| 615 | + const body = await result.text(); |
| 616 | + t.match(body, /<h1>OK!<\/h1>/); |
| 617 | + |
| 618 | + const podiumClient = new Client({ name: 'podiumClient' }); |
| 619 | + const podletClient = podiumClient.register({ |
| 620 | + name: 'foo', |
| 621 | + uri: `http://localhost:${server.address().port}/manifest.json`, |
| 622 | + }); |
| 623 | + |
| 624 | + const incoming = new HttpIncoming({ headers }); |
| 625 | + const response = await podletClient.fetch(incoming); |
| 626 | + |
| 627 | + t.equal(response.content, '<h1>OK!</h1>'); |
| 628 | + |
| 629 | + const css = response.css[0].toJSON(); |
| 630 | + t.equal(css.crossorigin, undefined); |
| 631 | + t.equal(css.disabled, undefined); |
| 632 | + t.equal(css.hreflang, undefined); |
| 633 | + t.equal(css.title, undefined); |
| 634 | + t.equal(css.value, '/styles.css'); |
| 635 | + t.equal(css.media, undefined); |
| 636 | + t.equal(css.type, 'text/css'); |
| 637 | + t.equal(css.rel, 'stylesheet'); |
| 638 | + t.equal(css.as, undefined); |
| 639 | + |
| 640 | + const js = response.js[0].toJSON(); |
| 641 | + t.equal(js.referrerpolicy, undefined); |
| 642 | + t.equal(js.crossorigin, undefined); |
| 643 | + t.equal(js.integrity, undefined); |
| 644 | + t.equal(js.nomodule, undefined); |
| 645 | + t.equal(js.value, '/scripts.js'); |
| 646 | + t.equal(js.async, 'true'); |
| 647 | + t.equal(js.defer, undefined); |
| 648 | + t.equal(js.type, 'module'); |
| 649 | + t.same(js.data, undefined); |
| 650 | + |
| 651 | + server.close(); |
| 652 | + }, |
| 653 | +); |
| 654 | + |
| 655 | +tap.test( |
| 656 | + 'assets - .js() and .css() - Link headers - sent and received earlier than body', |
| 657 | + async (t) => { |
| 658 | + const app = createPodletServer(); |
| 659 | + const server = app.listen(0); |
| 660 | + |
| 661 | + const podiumClient = new Client({ name: 'podiumClient' }); |
| 662 | + const podletClient = podiumClient.register({ |
| 663 | + name: 'foo', |
| 664 | + uri: `http://localhost:${server.address().port}/manifest.json`, |
| 665 | + }); |
| 666 | + |
| 667 | + let assetEnd; |
| 668 | + |
| 669 | + const incoming = new HttpIncoming({ headers }); |
| 670 | + const outgoing = podletClient.stream(incoming); |
| 671 | + outgoing.on('beforeStream', (response) => { |
| 672 | + assetEnd = new Date().getTime(); |
| 673 | + |
| 674 | + const css = response.css[0].toJSON(); |
| 675 | + t.equal(css.crossorigin, undefined); |
| 676 | + t.equal(css.disabled, undefined); |
| 677 | + t.equal(css.hreflang, undefined); |
| 678 | + t.equal(css.title, undefined); |
| 679 | + t.equal(css.value, '/styles.css'); |
| 680 | + t.equal(css.media, undefined); |
| 681 | + t.equal(css.type, 'text/css'); |
| 682 | + t.equal(css.rel, 'stylesheet'); |
| 683 | + t.equal(css.as, undefined); |
| 684 | + |
| 685 | + const js = response.js[0].toJSON(); |
| 686 | + t.equal(js.referrerpolicy, undefined); |
| 687 | + t.equal(js.crossorigin, undefined); |
| 688 | + t.equal(js.integrity, undefined); |
| 689 | + t.equal(js.nomodule, undefined); |
| 690 | + t.equal(js.value, '/scripts.js'); |
| 691 | + t.equal(js.async, 'true'); |
| 692 | + t.equal(js.defer, undefined); |
| 693 | + t.equal(js.type, 'module'); |
| 694 | + t.same(js.data, undefined); |
| 695 | + }); |
| 696 | + |
| 697 | + const content = []; |
| 698 | + for await (const chunk of outgoing) { |
| 699 | + content.push(chunk.toString()); |
| 700 | + } |
| 701 | + |
| 702 | + const bodyEnd = new Date().getTime(); |
| 703 | + // @ts-ignore |
| 704 | + const timeDiff = bodyEnd - assetEnd; |
| 705 | + |
| 706 | + t.ok(timeDiff > 800); |
| 707 | + |
| 708 | + t.equal(content[0], '<h1>OK!</h1>'); |
| 709 | + |
| 710 | + server.close(); |
| 711 | + }, |
| 712 | +); |
0 commit comments