mirror of
https://github.com/element-hq/element-web
synced 2024-11-25 18:55:58 +03:00
Move from browser-request
to fetch
(#23427)
This commit is contained in:
parent
326a1a9056
commit
2ef6abbfb8
8 changed files with 169 additions and 148 deletions
|
@ -119,6 +119,7 @@
|
||||||
"eslint-plugin-react-hooks": "^4.3.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||||
"fake-indexeddb": "^3.1.2",
|
"fake-indexeddb": "^3.1.2",
|
||||||
|
"fetch-mock-jest": "^1.5.1",
|
||||||
"file-loader": "^5.1.0",
|
"file-loader": "^5.1.0",
|
||||||
"fs-extra": "^0.30.0",
|
"fs-extra": "^0.30.0",
|
||||||
"html-webpack-plugin": "^4.5.2",
|
"html-webpack-plugin": "^4.5.2",
|
||||||
|
@ -130,7 +131,7 @@
|
||||||
"jest-sonar-reporter": "^2.0.0",
|
"jest-sonar-reporter": "^2.0.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"loader-utils": "^1.4.0",
|
"loader-utils": "^1.4.0",
|
||||||
"matrix-mock-request": "^2.0.0",
|
"matrix-mock-request": "^2.5.0",
|
||||||
"matrix-react-test-utils": "^0.2.3",
|
"matrix-react-test-utils": "^0.2.3",
|
||||||
"matrix-web-i18n": "^1.3.0",
|
"matrix-web-i18n": "^1.3.0",
|
||||||
"mini-css-extract-plugin": "^1",
|
"mini-css-extract-plugin": "^1",
|
||||||
|
@ -188,7 +189,6 @@
|
||||||
"\\.(gif|png|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",
|
"\\.(gif|png|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",
|
||||||
"\\.svg$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/svg.js",
|
"\\.svg$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/svg.js",
|
||||||
"\\$webapp/i18n/languages.json": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/languages.json",
|
"\\$webapp/i18n/languages.json": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/languages.json",
|
||||||
"^browser-request$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/browser-request.js",
|
|
||||||
"^react$": "<rootDir>/node_modules/react",
|
"^react$": "<rootDir>/node_modules/react",
|
||||||
"^react-dom$": "<rootDir>/node_modules/react-dom",
|
"^react-dom$": "<rootDir>/node_modules/react-dom",
|
||||||
"^matrix-js-sdk$": "<rootDir>/node_modules/matrix-js-sdk/src",
|
"^matrix-js-sdk$": "<rootDir>/node_modules/matrix-js-sdk/src",
|
||||||
|
|
|
@ -18,8 +18,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// To ensure we load the browser-request version
|
// To ensure we load the browser-matrix version first
|
||||||
import "matrix-js-sdk"; // eslint-disable-line no-restricted-imports
|
import "matrix-js-sdk/src/browser-index";
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||||
|
|
|
@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import request from 'browser-request';
|
|
||||||
|
|
||||||
import type { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions";
|
import type { IConfigOptions } from "matrix-react-sdk/src/IConfigOptions";
|
||||||
|
|
||||||
// Load the config file. First try to load up a domain-specific config of the
|
// Load the config file. First try to load up a domain-specific config of the
|
||||||
|
@ -32,44 +30,28 @@ export async function getVectorConfig(relativeLocation=''): Promise<IConfigOptio
|
||||||
if (Object.keys(configJson).length === 0) {
|
if (Object.keys(configJson).length === 0) {
|
||||||
throw new Error(); // throw to enter the catch
|
throw new Error(); // throw to enter the catch
|
||||||
}
|
}
|
||||||
return configJson as IConfigOptions;
|
return configJson;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return await generalConfigPromise as IConfigOptions;
|
return generalConfigPromise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConfig(configJsonFilename: string): Promise<{}> {
|
async function getConfig(configJsonFilename: string): Promise<IConfigOptions> {
|
||||||
return new Promise(function(resolve, reject) {
|
const url = new URL(configJsonFilename, window.location.href);
|
||||||
request(
|
url.searchParams.set("cachebuster", Date.now().toString());
|
||||||
{ method: "GET", url: configJsonFilename, qs: { cachebuster: Date.now() } },
|
const res = await fetch(url, {
|
||||||
(err, response, body) => {
|
cache: "no-cache",
|
||||||
try {
|
method: "GET",
|
||||||
if (err || response.status < 200 || response.status >= 300) {
|
|
||||||
// Lack of a config isn't an error, we should
|
|
||||||
// just use the defaults.
|
|
||||||
// Also treat a blank config as no config, assuming
|
|
||||||
// the status code is 0, because we don't get 404s
|
|
||||||
// from file: URIs so this is the only way we can
|
|
||||||
// not fail if the file doesn't exist when loading
|
|
||||||
// from a file:// URI.
|
|
||||||
if (response) {
|
|
||||||
if (response.status == 404 || (response.status == 0 && body == '')) {
|
|
||||||
resolve({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reject({ err: err, response: response });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We parse the JSON ourselves rather than use the JSON
|
|
||||||
// parameter, since this throws a parse error on empty
|
|
||||||
// which breaks if there's no config.json and we're
|
|
||||||
// loading from the filesystem (see above).
|
|
||||||
resolve(JSON.parse(body));
|
|
||||||
} catch (e) {
|
|
||||||
reject({ err: e });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (res.status === 404 || res.status === 0) {
|
||||||
|
// Lack of a config isn't an error, we should just use the defaults.
|
||||||
|
// Also treat a blank config as no config, assuming the status code is 0, because we don't get 404s from file:
|
||||||
|
// URIs so this is the only way we can not fail if the file doesn't exist when loading from a file:// URI.
|
||||||
|
return {} as IConfigOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { UpdateCheckStatus, UpdateStatus } from "matrix-react-sdk/src/BasePlatform";
|
import { UpdateCheckStatus, UpdateStatus } from "matrix-react-sdk/src/BasePlatform";
|
||||||
import request from 'browser-request';
|
|
||||||
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
|
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
|
||||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||||
import { hideToast as hideUpdateToast, showToast as showUpdateToast } from "matrix-react-sdk/src/toasts/UpdateToast";
|
import { hideToast as hideUpdateToast, showToast as showUpdateToast } from "matrix-react-sdk/src/toasts/UpdateToast";
|
||||||
|
@ -87,31 +86,17 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMostRecentVersion(): Promise<string> {
|
private async getMostRecentVersion(): Promise<string> {
|
||||||
// We add a cachebuster to the request to make sure that we know about
|
const res = await fetch("version", {
|
||||||
// the most recent version on the origin server. That might not
|
|
||||||
// actually be the version we'd get on a reload (particularly in the
|
|
||||||
// presence of intermediate caching proxies), but still: we're trying
|
|
||||||
// to tell the user that there is a new version.
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
request(
|
|
||||||
{
|
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "version",
|
cache: "no-cache",
|
||||||
qs: { cachebuster: Date.now() },
|
});
|
||||||
},
|
|
||||||
(err, response, body) => {
|
if (res.ok) {
|
||||||
if (err || response.status < 200 || response.status >= 300) {
|
return getNormalizedAppVersion(await res.text());
|
||||||
if (err === null) err = { status: response.status };
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(getNormalizedAppVersion(body.trim()));
|
return Promise.reject({ status: res.status });
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAppVersion(): Promise<string> {
|
public getAppVersion(): Promise<string> {
|
||||||
|
|
|
@ -41,6 +41,7 @@ import { RoomView as RoomViewClass } from 'matrix-react-sdk/src/components/struc
|
||||||
import LoginComponent from 'matrix-react-sdk/src/components/structures/auth/Login';
|
import LoginComponent from 'matrix-react-sdk/src/components/structures/auth/Login';
|
||||||
import WelcomeComponent from "matrix-react-sdk/src/components/views/auth/Welcome";
|
import WelcomeComponent from "matrix-react-sdk/src/components/views/auth/Welcome";
|
||||||
import EmbeddedPage from "matrix-react-sdk/src/components/structures/EmbeddedPage";
|
import EmbeddedPage from "matrix-react-sdk/src/components/structures/EmbeddedPage";
|
||||||
|
import { AutoDiscovery } from 'matrix-js-sdk/src/matrix';
|
||||||
|
|
||||||
const DEFAULT_HS_URL='http://my_server';
|
const DEFAULT_HS_URL='http://my_server';
|
||||||
const DEFAULT_IS_URL='http://my_is';
|
const DEFAULT_IS_URL='http://my_is';
|
||||||
|
@ -60,7 +61,7 @@ describe('loading:', function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
httpBackend = new MockHttpBackend();
|
httpBackend = new MockHttpBackend();
|
||||||
jssdk.request(httpBackend.requestFn);
|
window.fetch = httpBackend.fetchFn;
|
||||||
parentDiv = document.createElement('div');
|
parentDiv = document.createElement('div');
|
||||||
|
|
||||||
// uncomment this to actually add the div to the UI, to help with
|
// uncomment this to actually add the div to the UI, to help with
|
||||||
|
@ -73,7 +74,8 @@ describe('loading:', function() {
|
||||||
|
|
||||||
afterEach(async function() {
|
afterEach(async function() {
|
||||||
console.log(`${Date.now()}: loading: afterEach`);
|
console.log(`${Date.now()}: loading: afterEach`);
|
||||||
if (parentDiv) {
|
try {
|
||||||
|
if (matrixChat) {
|
||||||
ReactDOM.unmountComponentAtNode(parentDiv);
|
ReactDOM.unmountComponentAtNode(parentDiv);
|
||||||
parentDiv.remove();
|
parentDiv.remove();
|
||||||
parentDiv = null;
|
parentDiv = null;
|
||||||
|
@ -88,6 +90,9 @@ describe('loading:', function() {
|
||||||
test_utils.deleteIndexedDB('matrix-js-sdk:riot-web-sync'),
|
test_utils.deleteIndexedDB('matrix-js-sdk:riot-web-sync'),
|
||||||
]);
|
]);
|
||||||
cleanLocalstorage();
|
cleanLocalstorage();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
console.log(`${Date.now()}: loading: afterEach complete`);
|
console.log(`${Date.now()}: loading: afterEach complete`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -421,7 +426,6 @@ describe('loading:', function() {
|
||||||
|
|
||||||
describe('Guest auto-registration:', function() {
|
describe('Guest auto-registration:', function() {
|
||||||
it('shows a welcome page by default', function() {
|
it('shows a welcome page by default', function() {
|
||||||
|
|
||||||
loadApp();
|
loadApp();
|
||||||
|
|
||||||
return sleep(1).then(() => {
|
return sleep(1).then(() => {
|
||||||
|
|
|
@ -14,14 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import request from 'browser-request';
|
import fetchMock from "fetch-mock-jest";
|
||||||
|
|
||||||
import { getVectorConfig } from "../../../src/vector/getconfig";
|
import { getVectorConfig } from "../../../src/vector/getconfig";
|
||||||
|
|
||||||
describe('getVectorConfig()', () => {
|
fetchMock.config.overwriteRoutes = true;
|
||||||
const setRequestMockImplementationOnce = (err?: unknown, response?: { status: number }, body?: string) =>
|
|
||||||
request.mockImplementationOnce((_opts, callback) => callback(err, response, body));
|
|
||||||
|
|
||||||
|
describe('getVectorConfig()', () => {
|
||||||
const prevDocumentDomain = document.domain;
|
const prevDocumentDomain = document.domain;
|
||||||
const elementDomain = 'app.element.io';
|
const elementDomain = 'app.element.io';
|
||||||
const now = 1234567890;
|
const now = 1234567890;
|
||||||
|
@ -38,6 +37,7 @@ describe('getVectorConfig()', () => {
|
||||||
// stable value for cachebuster
|
// stable value for cachebuster
|
||||||
jest.spyOn(Date, 'now').mockReturnValue(now);
|
jest.spyOn(Date, 'now').mockReturnValue(now);
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
fetchMock.mockClear();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
@ -46,85 +46,67 @@ describe('getVectorConfig()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('requests specific config for document domain', async () => {
|
it('requests specific config for document domain', async () => {
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(specificConfig))
|
fetchMock.getOnce("express:/config.app.element.io.json", specificConfig);
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||||
|
|
||||||
await getVectorConfig();
|
await expect(getVectorConfig()).resolves.toEqual(specificConfig);
|
||||||
|
|
||||||
expect(request.mock.calls[0][0]).toEqual({ method: "GET", url: 'config.app.element.io.json', qs: { cachebuster: now } })
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds trailing slash to relativeLocation when not an empty string', async () => {
|
it('adds trailing slash to relativeLocation when not an empty string', async () => {
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(specificConfig))
|
fetchMock.getOnce("express:../config.app.element.io.json", specificConfig);
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:../config.json", generalConfig);
|
||||||
|
|
||||||
await getVectorConfig('..');
|
await expect(getVectorConfig("..")).resolves.toEqual(specificConfig);
|
||||||
|
|
||||||
expect(request.mock.calls[0][0]).toEqual(expect.objectContaining({ url: '../config.app.element.io.json' }))
|
|
||||||
expect(request.mock.calls[1][0]).toEqual(expect.objectContaining({ url: '../config.json' }))
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns parsed specific config when it is non-empty', async () => {
|
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(specificConfig))
|
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
|
||||||
|
|
||||||
const result = await getVectorConfig();
|
|
||||||
expect(result).toEqual(specificConfig);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns general config when specific config succeeds but is empty', async () => {
|
it('returns general config when specific config succeeds but is empty', async () => {
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify({}))
|
fetchMock.getOnce("express:/config.app.element.io.json", {});
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||||
|
|
||||||
const result = await getVectorConfig();
|
await expect(getVectorConfig()).resolves.toEqual(generalConfig);
|
||||||
expect(result).toEqual(generalConfig);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns general config when specific config 404s', async () => {
|
it('returns general config when specific config 404s', async () => {
|
||||||
setRequestMockImplementationOnce(undefined, { status: 404 })
|
fetchMock.getOnce("express:/config.app.element.io.json", { status: 404 });
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||||
|
|
||||||
const result = await getVectorConfig();
|
await expect(getVectorConfig()).resolves.toEqual(generalConfig);
|
||||||
expect(result).toEqual(generalConfig);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns general config when specific config is fetched from a file and is empty', async () => {
|
it('returns general config when specific config is fetched from a file and is empty', async () => {
|
||||||
setRequestMockImplementationOnce(undefined, { status: 0 }, '')
|
fetchMock.getOnce("express:/config.app.element.io.json", 0);
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||||
|
|
||||||
const result = await getVectorConfig();
|
await expect(getVectorConfig()).resolves.toEqual(generalConfig);
|
||||||
expect(result).toEqual(generalConfig);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns general config when specific config returns a non-200 status', async () => {
|
it('returns general config when specific config returns a non-200 status', async () => {
|
||||||
setRequestMockImplementationOnce(undefined, { status: 401 })
|
fetchMock.getOnce("express:/config.app.element.io.json", { status: 401 });
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||||
|
|
||||||
const result = await getVectorConfig();
|
await expect(getVectorConfig()).resolves.toEqual(generalConfig);
|
||||||
expect(result).toEqual(generalConfig);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns general config when specific config returns an error', async () => {
|
it('returns general config when specific config returns an error', async () => {
|
||||||
setRequestMockImplementationOnce('err1')
|
fetchMock.getOnce("express:/config.app.element.io.json", { throws: "err1" });
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, JSON.stringify(generalConfig))
|
fetchMock.getOnce("express:/config.json", generalConfig);
|
||||||
|
|
||||||
const result = await getVectorConfig();
|
await expect(getVectorConfig()).resolves.toEqual(generalConfig);
|
||||||
expect(result).toEqual(generalConfig);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects with an error when general config rejects', async () => {
|
it('rejects with an error when general config rejects', async () => {
|
||||||
setRequestMockImplementationOnce('err-specific');
|
fetchMock.getOnce("express:/config.app.element.io.json", { throws: "err-specific" });
|
||||||
setRequestMockImplementationOnce('err-general');
|
fetchMock.getOnce("express:/config.json", { throws: "err-general" });
|
||||||
|
|
||||||
await expect(() => getVectorConfig()).rejects.toEqual({"err": "err-general", "response": undefined});
|
await expect(getVectorConfig()).rejects.toBe("err-general");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects with an error when config is invalid JSON', async () => {
|
it('rejects with an error when config is invalid JSON', async () => {
|
||||||
setRequestMockImplementationOnce('err-specific');
|
fetchMock.getOnce("express:/config.app.element.io.json", { throws: "err-specific" });
|
||||||
setRequestMockImplementationOnce(undefined, { status: 200 }, '{"invalid": "json",}');
|
fetchMock.getOnce("express:/config.json", '{"invalid": "json",}');
|
||||||
|
|
||||||
await expect(() => getVectorConfig()).rejects.toEqual({
|
// We can't assert it'll be a SyntaxError as node-fetch behaves differently
|
||||||
err: new SyntaxError("Unexpected token } in JSON at position 19"),
|
// https://github.com/wheresrhys/fetch-mock/issues/270
|
||||||
});
|
await expect(getVectorConfig()).rejects.toThrow("Unexpected token } in JSON at position 19");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,12 +14,14 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import request from 'browser-request';
|
import fetchMock from "fetch-mock-jest";
|
||||||
import { UpdateCheckStatus } from 'matrix-react-sdk/src/BasePlatform';
|
import { UpdateCheckStatus } from 'matrix-react-sdk/src/BasePlatform';
|
||||||
import { MatrixClientPeg } from 'matrix-react-sdk/src/MatrixClientPeg';
|
import { MatrixClientPeg } from 'matrix-react-sdk/src/MatrixClientPeg';
|
||||||
|
|
||||||
import WebPlatform from '../../../../src/vector/platform/WebPlatform';
|
import WebPlatform from '../../../../src/vector/platform/WebPlatform';
|
||||||
|
|
||||||
|
fetchMock.config.overwriteRoutes = true;
|
||||||
|
|
||||||
describe('WebPlatform', () => {
|
describe('WebPlatform', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
@ -120,9 +122,6 @@ describe('WebPlatform', () => {
|
||||||
const envVersion = process.env.VERSION;
|
const envVersion = process.env.VERSION;
|
||||||
const prodVersion = '1.10.13';
|
const prodVersion = '1.10.13';
|
||||||
|
|
||||||
const setRequestMockImplementation = (err?: unknown, response?: { status: number }, body?: string) =>
|
|
||||||
request.mockImplementation((_opts, callback) => callback(err, response, body));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(MatrixClientPeg, 'userRegisteredWithinLastHours').mockReturnValue(false);
|
jest.spyOn(MatrixClientPeg, 'userRegisteredWithinLastHours').mockReturnValue(false);
|
||||||
})
|
})
|
||||||
|
@ -157,7 +156,7 @@ describe('WebPlatform', () => {
|
||||||
describe('pollForUpdate()', () => {
|
describe('pollForUpdate()', () => {
|
||||||
it('should return not available and call showNoUpdate when current version matches most recent version', async () => {
|
it('should return not available and call showNoUpdate when current version matches most recent version', async () => {
|
||||||
process.env.VERSION = prodVersion;
|
process.env.VERSION = prodVersion;
|
||||||
setRequestMockImplementation(undefined, { status: 200}, prodVersion);
|
fetchMock.getOnce("/version", prodVersion);
|
||||||
const platform = new WebPlatform();
|
const platform = new WebPlatform();
|
||||||
|
|
||||||
const showUpdate = jest.fn();
|
const showUpdate = jest.fn();
|
||||||
|
@ -171,7 +170,7 @@ describe('WebPlatform', () => {
|
||||||
|
|
||||||
it('should strip v prefix from versions before comparing', async () => {
|
it('should strip v prefix from versions before comparing', async () => {
|
||||||
process.env.VERSION = prodVersion;
|
process.env.VERSION = prodVersion;
|
||||||
setRequestMockImplementation(undefined, { status: 200}, `v${prodVersion}`);
|
fetchMock.getOnce("/version", `v${prodVersion}`);
|
||||||
const platform = new WebPlatform();
|
const platform = new WebPlatform();
|
||||||
|
|
||||||
const showUpdate = jest.fn();
|
const showUpdate = jest.fn();
|
||||||
|
@ -186,7 +185,7 @@ describe('WebPlatform', () => {
|
||||||
|
|
||||||
it('should return ready and call showUpdate when current version differs from most recent version', async () => {
|
it('should return ready and call showUpdate when current version differs from most recent version', async () => {
|
||||||
process.env.VERSION = '0.0.0'; // old version
|
process.env.VERSION = '0.0.0'; // old version
|
||||||
setRequestMockImplementation(undefined, { status: 200}, prodVersion);
|
fetchMock.getOnce("/version", prodVersion);
|
||||||
const platform = new WebPlatform();
|
const platform = new WebPlatform();
|
||||||
|
|
||||||
const showUpdate = jest.fn();
|
const showUpdate = jest.fn();
|
||||||
|
@ -201,7 +200,7 @@ describe('WebPlatform', () => {
|
||||||
it('should return ready without showing update when user registered in last 24', async () => {
|
it('should return ready without showing update when user registered in last 24', async () => {
|
||||||
process.env.VERSION = '0.0.0'; // old version
|
process.env.VERSION = '0.0.0'; // old version
|
||||||
jest.spyOn(MatrixClientPeg, 'userRegisteredWithinLastHours').mockReturnValue(true);
|
jest.spyOn(MatrixClientPeg, 'userRegisteredWithinLastHours').mockReturnValue(true);
|
||||||
setRequestMockImplementation(undefined, { status: 200}, prodVersion);
|
fetchMock.getOnce("/version", prodVersion);
|
||||||
const platform = new WebPlatform();
|
const platform = new WebPlatform();
|
||||||
|
|
||||||
const showUpdate = jest.fn();
|
const showUpdate = jest.fn();
|
||||||
|
@ -214,7 +213,7 @@ describe('WebPlatform', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return error when version check fails', async () => {
|
it('should return error when version check fails', async () => {
|
||||||
setRequestMockImplementation('oups');
|
fetchMock.getOnce("/version", { throws: "oups" });
|
||||||
const platform = new WebPlatform();
|
const platform = new WebPlatform();
|
||||||
|
|
||||||
const showUpdate = jest.fn();
|
const showUpdate = jest.fn();
|
||||||
|
|
81
yarn.lock
81
yarn.lock
|
@ -47,7 +47,7 @@
|
||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.3.tgz#707b939793f867f5a73b2666e6d9a3396eb03151"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.3.tgz#707b939793f867f5a73b2666e6d9a3396eb03151"
|
||||||
integrity sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==
|
integrity sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==
|
||||||
|
|
||||||
"@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3":
|
"@babel/core@^7.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3":
|
||||||
version "7.19.3"
|
version "7.19.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c"
|
||||||
integrity sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==
|
integrity sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==
|
||||||
|
@ -3978,6 +3978,11 @@ core-js@^2.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||||
|
|
||||||
|
core-js@^3.0.0:
|
||||||
|
version "3.25.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27"
|
||||||
|
integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==
|
||||||
|
|
||||||
core-js@^3.4:
|
core-js@^3.4:
|
||||||
version "3.24.1"
|
version "3.24.1"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f"
|
||||||
|
@ -5670,6 +5675,29 @@ fbjs@^0.8.4:
|
||||||
setimmediate "^1.0.5"
|
setimmediate "^1.0.5"
|
||||||
ua-parser-js "^0.7.30"
|
ua-parser-js "^0.7.30"
|
||||||
|
|
||||||
|
fetch-mock-jest@^1.5.1:
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fetch-mock-jest/-/fetch-mock-jest-1.5.1.tgz#0e13df990d286d9239e284f12b279ed509bf53cd"
|
||||||
|
integrity sha512-+utwzP8C+Pax1GSka3nFXILWMY3Er2L+s090FOgqVNrNCPp0fDqgXnAHAJf12PLHi0z4PhcTaZNTz8e7K3fjqQ==
|
||||||
|
dependencies:
|
||||||
|
fetch-mock "^9.11.0"
|
||||||
|
|
||||||
|
fetch-mock@^9.11.0:
|
||||||
|
version "9.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-9.11.0.tgz#371c6fb7d45584d2ae4a18ee6824e7ad4b637a3f"
|
||||||
|
integrity sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "^7.0.0"
|
||||||
|
"@babel/runtime" "^7.0.0"
|
||||||
|
core-js "^3.0.0"
|
||||||
|
debug "^4.1.1"
|
||||||
|
glob-to-regexp "^0.4.0"
|
||||||
|
is-subset "^0.1.1"
|
||||||
|
lodash.isequal "^4.5.0"
|
||||||
|
path-to-regexp "^2.2.1"
|
||||||
|
querystring "^0.2.0"
|
||||||
|
whatwg-url "^6.5.0"
|
||||||
|
|
||||||
fflate@^0.4.1:
|
fflate@^0.4.1:
|
||||||
version "0.4.8"
|
version "0.4.8"
|
||||||
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
|
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
|
||||||
|
@ -6139,7 +6167,7 @@ glob-to-regexp@^0.3.0:
|
||||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
|
||||||
integrity sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==
|
integrity sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==
|
||||||
|
|
||||||
glob-to-regexp@^0.4.1:
|
glob-to-regexp@^0.4.0, glob-to-regexp@^0.4.1:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
||||||
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||||
|
@ -7179,6 +7207,11 @@ is-string@^1.0.5, is-string@^1.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
|
is-subset@^0.1.1:
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6"
|
||||||
|
integrity sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==
|
||||||
|
|
||||||
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
|
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
|
||||||
|
@ -8095,6 +8128,11 @@ lodash.debounce@^4.0.8:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||||
|
|
||||||
|
lodash.isequal@^4.5.0:
|
||||||
|
version "4.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||||
|
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||||
|
|
||||||
lodash.memoize@^4.1.2:
|
lodash.memoize@^4.1.2:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||||
|
@ -8105,6 +8143,11 @@ lodash.merge@^4.6.2:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||||
|
|
||||||
|
lodash.sortby@^4.7.0:
|
||||||
|
version "4.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||||
|
integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
|
||||||
|
|
||||||
lodash.truncate@^4.4.2:
|
lodash.truncate@^4.4.2:
|
||||||
version "4.4.2"
|
version "4.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||||
|
@ -8285,10 +8328,10 @@ matrix-events-sdk@^0.0.1-beta.7:
|
||||||
request "^2.88.2"
|
request "^2.88.2"
|
||||||
unhomoglyph "^1.0.6"
|
unhomoglyph "^1.0.6"
|
||||||
|
|
||||||
matrix-mock-request@^2.0.0:
|
matrix-mock-request@^2.5.0:
|
||||||
version "2.1.2"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/matrix-mock-request/-/matrix-mock-request-2.1.2.tgz#11e38ed1233dced88a6f2bfba1684d5c5b3aa2c2"
|
resolved "https://registry.yarnpkg.com/matrix-mock-request/-/matrix-mock-request-2.5.0.tgz#78da2590e82be2e31edcf9814833af5e5f8d2f1a"
|
||||||
integrity sha512-/OXCIzDGSLPJ3fs+uzDrtaOHI/Sqp4iEuniRn31U8S06mPXbvAnXknHqJ4c6A/KVwJj/nPFbGXpK4wPM038I6A==
|
integrity sha512-7T3gklpW+4rfHsTnp/FDML7aWoBrXhAh8+1ltinQfAh9TDj6y382z/RUMR7i03d1WDzt/ed1UTihqO5GDoOq9Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
expect "^28.1.0"
|
expect "^28.1.0"
|
||||||
|
|
||||||
|
@ -9421,6 +9464,11 @@ path-to-regexp@0.1.7:
|
||||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
||||||
|
|
||||||
|
path-to-regexp@^2.2.1:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704"
|
||||||
|
integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==
|
||||||
|
|
||||||
path-type@^3.0.0:
|
path-type@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
||||||
|
@ -10488,6 +10536,11 @@ querystring@0.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||||
integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==
|
integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==
|
||||||
|
|
||||||
|
querystring@^0.2.0:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
|
||||||
|
integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
|
||||||
|
|
||||||
querystringify@^2.1.1:
|
querystringify@^2.1.1:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
|
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
|
||||||
|
@ -12181,6 +12234,13 @@ tough-cookie@~2.5.0:
|
||||||
psl "^1.1.28"
|
psl "^1.1.28"
|
||||||
punycode "^2.1.1"
|
punycode "^2.1.1"
|
||||||
|
|
||||||
|
tr46@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
||||||
|
integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==
|
||||||
|
dependencies:
|
||||||
|
punycode "^2.1.0"
|
||||||
|
|
||||||
tr46@^2.1.0:
|
tr46@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
|
||||||
|
@ -12903,6 +12963,15 @@ whatwg-url@^5.0.0:
|
||||||
tr46 "~0.0.3"
|
tr46 "~0.0.3"
|
||||||
webidl-conversions "^3.0.0"
|
webidl-conversions "^3.0.0"
|
||||||
|
|
||||||
|
whatwg-url@^6.5.0:
|
||||||
|
version "6.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
|
||||||
|
integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
|
||||||
|
dependencies:
|
||||||
|
lodash.sortby "^4.7.0"
|
||||||
|
tr46 "^1.0.1"
|
||||||
|
webidl-conversions "^4.0.2"
|
||||||
|
|
||||||
whatwg-url@^8.4.0:
|
whatwg-url@^8.4.0:
|
||||||
version "8.7.0"
|
version "8.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
|
||||||
|
|
Loading…
Reference in a new issue