Make shared component build work in isolation (#31066)
* Make shared component build work in isolation * Add deps that were missing because they were getting picked up from element-web main but shared-components needs itself * Exclude test files from dts generation * Bump version * Change all the shared-component import to be the built artifact * Don't randomly inhale eslint configs in parent dirs please * maybe we don't need this anymore? * maybe fix build * Maybe fix docker build * More build faff * build:res on the parent as part of shared component prepare * link shared component repo inn docker build * 💅 * 💅x2 * Try converting the translation keys to a .d.ts file manually so it gets bundled rather than left as a relative import to the json file * add the script * Add this back for 2nd time now I think * Shouldn't need this anymore * patch-package on prepare because we're patching a dev dependency so it won't be there if we're installed as a dependency * Unused import * Prettier compliance * Only use counterpart from shared components as per comment * Import shared components CSS * Prettier * Call the one from shared components rather than recurse infinitely * Hopefully make tests work * wake up, comment goes before import * Fix lint errors * Fix dupe TranslationKey export * Update compound-web to fix type error An update to @types.react adds the 'hint' value to the enum of the 'popover' attribute and this version of compound-web uses the maching verson of @types/react so they don't conflict. * Maybe, hopefully, get the types working? Please? * Add copyright header to i18nkeys as eslint complains otherwise since it's now in src * prettier * stop running shared-component tests in EW * update snapshots because flex is now from an external stylesheet I guess * More snapshots * Manual class update * Avoid bundling compound bits Because a) it's silly and b) it means we end up bundling a copy of floating-ui too which causes absolute madness with its useDelayGroup contexts. * ignore test util files for coverage * Add !important because the styles are being applied in a different order now * Another !important because css order has changed * Try adding it here to make the test files ignored * More !important * commit yarn lock change * Add shared components coverage file * Update snapshots Because the line height was being overridden to 22.5px somehow by something I can't find, and now isn't: surely the normal 1.5rem is more sensible. * Update snapshots, attempt 2 * Another !important * More snapshot updates * Add test for i18n wrappers & add test script * lint * Prettier * Hopefully run shared component tests * don't need this bit for non-matrix * install ew deps * rigfht coverage location * Rename job here too * Try different coverage filename * Fix copyrights & comment * Typo Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
.audioPlayer {
|
||||
padding: var(--cpd-space-4x) var(--cpd-space-3x) var(--cpd-space-3x) var(--cpd-space-3x);
|
||||
padding: var(--cpd-space-4x) var(--cpd-space-3x) var(--cpd-space-3x) var(--cpd-space-3x) !important;
|
||||
}
|
||||
|
||||
.mediaInfo {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`AudioPlayerView renders the audio player in default state 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`Clock renders the clock 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
*/
|
||||
|
||||
.button {
|
||||
border-radius: 32px;
|
||||
background-color: var(--cpd-color-bg-subtle-primary);
|
||||
border-radius: 32px !important;
|
||||
background-color: var(--cpd-color-bg-subtle-primary) !important;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`PlayPauseButton renders the button in default state 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`Seekbar renders the clock 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`AvatarWithDetails renders a textual event 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`TextualEventView renders a textual event 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -5,4 +5,4 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
export { TextualEventView } from "./TextualEventView";
|
||||
export { TextualEventView, type TextualEventViewSnapshot } from "./TextualEventView";
|
||||
|
||||
@@ -21,12 +21,17 @@ export * from "./utils/Box";
|
||||
export * from "./utils/Flex";
|
||||
|
||||
// Utils
|
||||
export { setLanguage } from "./utils/i18n";
|
||||
export * from "./utils/i18n";
|
||||
export * from "./utils/humanize";
|
||||
export * from "./utils/DateUtils";
|
||||
export * from "./utils/numbers";
|
||||
export * from "./utils/FormattingUtils";
|
||||
|
||||
// MVVM
|
||||
export * from "./viewmodel";
|
||||
export * from "./useMockedViewModel";
|
||||
export * from "./useViewModel";
|
||||
|
||||
// i18n (we must export this directly in order to not confuse the type bundler, it seems,
|
||||
// otherwise it will leave it as a relative import rather than bundling it)
|
||||
export type * from "./i18nKeys.d.ts";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
.mediaBody {
|
||||
background-color: var(--cpd-color-bg-subtle-secondary);
|
||||
border-radius: var(--cpd-space-2x);
|
||||
border-radius: var(--cpd-space-2x) !important;
|
||||
max-width: 243px; /* use max-width instead of width so it fits within right panels */
|
||||
|
||||
font: var(--cpd-font-body-md-regular);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`MediaBody renders the media body 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`Pill renders the pill 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`PillInput renders only the input without children 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`RichItem renders the item in default state 1`] = `
|
||||
<div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`RichItem renders the list 1`] = `
|
||||
<div>
|
||||
|
||||
22
packages/shared-components/src/test/setupTests.ts
Normal file
22
packages/shared-components/src/test/setupTests.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2025 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
|
||||
import { setLanguage } from "../../src/utils/i18n";
|
||||
import en from "../../../../src/i18n/strings/en_EN.json";
|
||||
|
||||
export function setupLanguageMock(): void {
|
||||
fetchMock
|
||||
.get("/i18n/languages.json", {
|
||||
en: "en_EN.json",
|
||||
})
|
||||
.get("end:en_EN.json", en);
|
||||
}
|
||||
setupLanguageMock();
|
||||
|
||||
setLanguage("en");
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2025 Element Creations Ltd.
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
// Copied from element-web/test/test-utils because, seemingly, if we
|
||||
// set that as the modules directory to use it directly, it fails to
|
||||
// actually put the right thing in the context somehow.
|
||||
|
||||
import React, { type ReactElement } from "react";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { render, type RenderOptions } from "@testing-library/react";
|
||||
import { TooltipProvider } from "@vector-im/compound-web";
|
||||
|
||||
const wrapWithTooltipProvider = (Wrapper: RenderOptions["wrapper"]) => {
|
||||
return ({ children }: { children: React.ReactNode }) => {
|
||||
if (Wrapper) {
|
||||
return (
|
||||
<Wrapper>
|
||||
<TooltipProvider>{children}</TooltipProvider>
|
||||
</Wrapper>
|
||||
);
|
||||
} else {
|
||||
return <TooltipProvider>{children}</TooltipProvider>;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const customRender = (ui: ReactElement, options: RenderOptions = {}): ReturnType<typeof render> => {
|
||||
return render(ui, {
|
||||
...options,
|
||||
wrapper: wrapWithTooltipProvider(options?.wrapper) as RenderOptions["wrapper"],
|
||||
}) as ReturnType<typeof render>;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
export * from "@testing-library/react";
|
||||
|
||||
/**
|
||||
* This custom render function wraps your component with a TooltipProvider.
|
||||
* See https://testing-library.com/docs/react-testing-library/setup/#custom-render
|
||||
*/
|
||||
export { customRender as render };
|
||||
46
packages/shared-components/src/utils/i18n.test.ts
Normal file
46
packages/shared-components/src/utils/i18n.test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import counterpart from "counterpart";
|
||||
|
||||
import { registerTranslations, setMissingEntryGenerator, getLocale, setLocale } from "./i18n";
|
||||
|
||||
describe("i18n utils", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should wrap registerTranslations", () => {
|
||||
jest.spyOn(counterpart, "registerTranslations");
|
||||
|
||||
registerTranslations("en", { test: "This is a test" });
|
||||
expect(counterpart.registerTranslations).toHaveBeenCalledWith("en", { test: "This is a test" });
|
||||
});
|
||||
|
||||
it("should wrap setMissingEntryGenerator", () => {
|
||||
jest.spyOn(counterpart, "setMissingEntryGenerator");
|
||||
|
||||
const dummyFn = jest.fn();
|
||||
|
||||
setMissingEntryGenerator(dummyFn);
|
||||
expect(counterpart.setMissingEntryGenerator).toHaveBeenCalledWith(dummyFn);
|
||||
});
|
||||
|
||||
it("should wrap getLocale", () => {
|
||||
jest.spyOn(counterpart, "getLocale");
|
||||
|
||||
getLocale();
|
||||
expect(counterpart.getLocale).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should wrap setLocale", () => {
|
||||
jest.spyOn(counterpart, "setLocale");
|
||||
|
||||
setLocale("en");
|
||||
expect(counterpart.setLocale).toHaveBeenCalledWith("en");
|
||||
});
|
||||
});
|
||||
@@ -22,10 +22,10 @@
|
||||
* @return a React <span> component if any non-strings were used in substitutions, otherwise a string
|
||||
*/
|
||||
import React from "react";
|
||||
import { type TranslationKey as _TranslationKey, KEY_SEPARATOR } from "matrix-web-i18n";
|
||||
import { KEY_SEPARATOR } from "matrix-web-i18n";
|
||||
import counterpart from "counterpart";
|
||||
|
||||
import type Translations from "../../../../src/i18n/strings/en_EN.json";
|
||||
import type { TranslationKey } from "../index";
|
||||
|
||||
// @ts-ignore - $webapp is a webpack resolve alias pointing to the output directory, see webpack config
|
||||
import webpackLangJsonUrl from "$webapp/i18n/languages.json";
|
||||
@@ -45,16 +45,23 @@ counterpart.setSeparator(KEY_SEPARATOR);
|
||||
const FALLBACK_LOCALE = "en";
|
||||
counterpart.setFallbackLocale(FALLBACK_LOCALE);
|
||||
|
||||
/**
|
||||
* A type representing the union of possible keys into the translation file using `|` delimiter to access nested fields.
|
||||
* @example `common|error` to access `error` within the `common` sub-object.
|
||||
* {
|
||||
* "common": {
|
||||
* "error": "Error"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export type TranslationKey = _TranslationKey<typeof Translations>;
|
||||
// export wrappers around these functions because if we used counterpart directly from
|
||||
// element-web, it operates on a different instance of counterpart
|
||||
export function registerTranslations(locale: string, data: object): void {
|
||||
counterpart.registerTranslations(locale, data);
|
||||
}
|
||||
|
||||
export function setMissingEntryGenerator(callback: (value: string) => void): void {
|
||||
counterpart.setMissingEntryGenerator(callback);
|
||||
}
|
||||
|
||||
export function getLocale(): string {
|
||||
return counterpart.getLocale();
|
||||
}
|
||||
|
||||
export function setLocale(value: string): string {
|
||||
return counterpart.setLocale(value);
|
||||
}
|
||||
|
||||
// Function which only purpose is to mark that a string is translatable
|
||||
// Does not actually do anything. It's helpful for automatic extraction of translatable strings
|
||||
|
||||
Reference in New Issue
Block a user