server-selection.spec.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. const { test, expect } = require('@playwright/test');
  2. const fs = require('node:fs');
  3. const path = require('node:path');
  4. const vm = require('node:vm');
  5. const speedtestSource = fs.readFileSync(
  6. path.resolve(__dirname, '../../speedtest.js'),
  7. 'utf8'
  8. );
  9. function createHarness(protocol, responders = {}) {
  10. const requests = [];
  11. function FakeXMLHttpRequest() {
  12. this.responseText = '';
  13. this.timeout = 0;
  14. }
  15. FakeXMLHttpRequest.prototype.open = function open(method, url) {
  16. this._method = method;
  17. this._url = url;
  18. };
  19. FakeXMLHttpRequest.prototype.send = function send() {
  20. requests.push(this._url);
  21. const baseUrl = this._url.replace(/[?&]cors=true$/, '');
  22. const outcome = responders[baseUrl] || 'error';
  23. if (outcome === 'success') {
  24. if (typeof this.onload === 'function') {
  25. this.onload();
  26. }
  27. return;
  28. }
  29. if (typeof this.onerror === 'function') {
  30. this.onerror(new Error(`Request failed for ${baseUrl}`));
  31. }
  32. };
  33. const context = {
  34. console: { log() {} },
  35. Date,
  36. location: { protocol },
  37. navigator: { userAgent: 'Playwright' },
  38. performance: { getEntriesByName: () => [] },
  39. XMLHttpRequest: FakeXMLHttpRequest
  40. };
  41. vm.createContext(context);
  42. vm.runInContext(speedtestSource, context, { filename: 'speedtest.js' });
  43. return { Speedtest: context.Speedtest, requests };
  44. }
  45. function createServer(server) {
  46. return {
  47. name: server,
  48. server,
  49. dlURL: 'garbage.php',
  50. ulURL: 'empty.php',
  51. pingURL: 'empty.php',
  52. getIpURL: 'getIP.php'
  53. };
  54. }
  55. function selectServer(speedtest) {
  56. return new Promise((resolve) => {
  57. speedtest.selectServer(resolve);
  58. });
  59. }
  60. test.describe('Speedtest server selection protocol handling', () => {
  61. test('allows HTTPS backends to be pinged from an HTTP frontend', async () => {
  62. const secureServer = 'https://secure.example/';
  63. const { Speedtest, requests } = createHarness('http:', {
  64. [`${secureServer}empty.php`]: 'success'
  65. });
  66. const speedtest = new Speedtest();
  67. speedtest.addTestPoint(createServer(secureServer));
  68. const selectedServer = await selectServer(speedtest);
  69. expect(selectedServer.server).toBe(secureServer);
  70. expect(
  71. requests.some((url) => url.startsWith(`${secureServer}empty.php`))
  72. ).toBeTruthy();
  73. });
  74. test('still skips insecure HTTP backends from an HTTPS frontend', async () => {
  75. const insecureServer = 'http://insecure.example/';
  76. const secureServer = 'https://secure.example/';
  77. const { Speedtest, requests } = createHarness('https:', {
  78. [`${insecureServer}empty.php`]: 'success',
  79. [`${secureServer}empty.php`]: 'success'
  80. });
  81. const speedtest = new Speedtest();
  82. speedtest.addTestPoint(createServer(insecureServer));
  83. speedtest.addTestPoint(createServer(secureServer));
  84. const selectedServer = await selectServer(speedtest);
  85. expect(selectedServer.server).toBe(secureServer);
  86. expect(
  87. requests.some((url) => url.startsWith(`${insecureServer}empty.php`))
  88. ).toBeFalsy();
  89. expect(
  90. requests.some((url) => url.startsWith(`${secureServer}empty.php`))
  91. ).toBeTruthy();
  92. });
  93. });