Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions manifest.chromium.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
},
"default_title": "Modify Outgoing XHR/Fetch Request Headers"
},
"options_ui": {
"page": "options.html",
"open_in_tab": true
},
"icons": {
"16": "img/main-icon-16.jpg",
"32": "img/main-icon-32.jpg",
Expand Down
4 changes: 4 additions & 0 deletions manifest.dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
},
"default_title": "Modify Outgoing XHR/Fetch Request Headers"
},
"options_ui": {
"page": "options.html",
"open_in_tab": true
},
"icons": {
"16": "img/main-icon-16.jpg",
"32": "img/main-icon-32.jpg",
Expand Down
4 changes: 4 additions & 0 deletions manifest.firefox.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
},
"default_title": "Modify Outgoing XHR/Fetch Request Headers"
},
"options_ui": {
"page": "options.html",
"open_in_tab": true
},
"icons": {
"16": "img/main-icon-16.jpg",
"32": "img/main-icon-32.jpg",
Expand Down
9 changes: 9 additions & 0 deletions scripts/check-extension-builds.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,20 @@ function readManifest(browser) {

function checkCommonBuild(browser, manifest) {
const backgroundPath = resolve(rootDir, `build/${browser}/background.bundle.js`);
const optionsPath = resolve(rootDir, `build/${browser}/options.html`);

if (!existsSync(backgroundPath)) {
errors.push(`Missing build/${browser}/background.bundle.js.`);
}

if (!existsSync(optionsPath)) {
errors.push(`Missing build/${browser}/options.html.`);
}

if (manifest?.options_ui?.page !== 'options.html') {
errors.push(`${browser} manifest must register options_ui.page as options.html.`);
}

if (manifest?.manifest_version !== 3) {
errors.push(`${browser} manifest must use manifest_version 3.`);
}
Expand Down
18 changes: 16 additions & 2 deletions scripts/firefox-e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ async function waitForValue(browser, selector, expected, index = 0) {
await waitUntil(async () => (await browser.value(selector, index)) === expected, `${selector} value "${expected}"`);
}

async function waitForStoredText(browser, text) {
await waitUntil(async () => {
const data = await browser.storage();
const profiles = data[STORAGE_KEYS.profiles];
return typeof profiles === 'string' && profiles.includes(text);
}, `storage to contain "${text}"`);
}

async function waitForCount(browser, selector, expected) {
await waitUntil(async () => (await browser.count(selector)) === expected, `${selector} count ${expected}`);
}
Expand Down Expand Up @@ -366,6 +374,8 @@ async function main() {
async () => {
await browser.fill(selectors.headerNameInput, 'X-Persisted');
await browser.fill(selectors.headerValueInput, 'persisted-value');
await waitForStoredText(browser, 'X-Persisted');
await waitForStoredText(browser, 'persisted-value');
await browser.refresh();
await waitForValue(browser, selectors.headerNameInput, 'X-Persisted');
await waitForValue(browser, selectors.headerValueInput, 'persisted-value');
Expand Down Expand Up @@ -424,6 +434,7 @@ async function main() {
async () => {
await browser.clickTab('URL Filters');
await browser.fill(selectors.urlFilterInput, 'https://persisted.example.com/*');
await waitForStoredText(browser, 'https://persisted.example.com/*');
await browser.refresh();
await browser.clickTab('URL Filters');
await waitForValue(browser, selectors.urlFilterInput, 'https://persisted.example.com/*');
Expand Down Expand Up @@ -526,6 +537,7 @@ async function main() {
assert.equal(await browser.count(selectors.urlFilterInput), 0);
await browser.click(selectors.addUrlFilterButton);
await browser.fill(selectors.urlFilterInput, 'https://legacy.example.com/*');
await waitForStoredText(browser, 'https://legacy.example.com/*');
await browser.refresh();
await browser.clickTab('URL Filters');
await waitForValue(browser, selectors.urlFilterInput, 'https://legacy.example.com/*');
Expand All @@ -536,7 +548,8 @@ async function main() {
async () => {
await browser.fill(selectors.headerNameInput, 'X-Cloudhood-Firefox');
await browser.fill(selectors.headerValueInput, 'active');
await waitUntil(async () => (await browser.dynamicRules()).length === 1, 'one Firefox DNR rule');
await waitForStoredText(browser, 'X-Cloudhood-Firefox');
await waitUntil(async () => (await browser.dynamicRules()).length === 1, 'one Firefox DNR rule', 15_000);
await expectEchoedHeader(driver, `${echoServer.url}/active`, 'X-Cloudhood-Firefox', 'active');
await browser.open();
await browser.click(selectors.pauseButton);
Expand All @@ -554,7 +567,8 @@ async function main() {
await browser.fill(selectors.headerValueInput, 'matched');
await browser.clickTab('URL Filters');
await browser.fill(selectors.urlFilterInput, `${echoServer.url}/matched*`);
await waitUntil(async () => (await browser.dynamicRules()).length === 1, 'one filtered Firefox DNR rule');
await waitForStoredText(browser, `${echoServer.url}/matched*`);
await waitUntil(async () => (await browser.dynamicRules()).length === 1, 'one filtered Firefox DNR rule', 15_000);
await expectEchoedHeader(driver, `${echoServer.url}/matched-path`, 'X-Cloudhood-Filtered', 'matched');
await expectEchoedHeader(driver, `${echoServer.url}/other-path`, 'X-Cloudhood-Filtered', undefined);
},
Expand Down
46 changes: 32 additions & 14 deletions scripts/firefox-screenshots.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const selectors = {
urlFilterMenuButton: '[data-test-id="url-filter-menu-button"]',
pauseButton: '[data-test-id="pause-button"]',
themeToggle: '[data-test-id="theme-toggle-button"]',
settingsButton: '[data-test-id="settings-button"]',
settingsPage: '[data-test-id="settings-page"]',
profileActionsButton: '[data-test-id="profile-actions-menu-button"]',
addProfileButton: '[data-test-id="add-profile-button"]',
profileSelect: '[data-test-id="profile-select"]',
Expand All @@ -56,6 +58,9 @@ const scenarios = [
scenario('general', 'theme-menu-open', async ({ click }) => {
await click(selectors.themeToggle);
}),
scenario('settings', 'settings-page', async ({ openOptions }) => {
await openOptions();
}),
scenario('headers', 'empty-state', async ({ activateHeaders }) => {
await activateHeaders();
}),
Expand Down Expand Up @@ -150,12 +155,16 @@ const scenarios = [
await removeAllUrlFilters();
await waitText('Remove all URL filters');
}),
scenario('modals', 'cookies-delete-confirmation', async ({ activateCookies, addCookie, removeAllCookies, waitText }) => {
await activateCookies();
await addCookie('session_id', 'abc123');
await removeAllCookies();
await waitText('Remove all request cookies');
}),
scenario(
'modals',
'cookies-delete-confirmation',
async ({ activateCookies, addCookie, removeAllCookies, waitText }) => {
await activateCookies();
await addCookie('session_id', 'abc123');
await removeAllCookies();
await waitText('Remove all request cookies');
},
),
scenario('profiles', 'single-profile', async ({ activateHeaders }) => {
await activateHeaders();
}),
Expand Down Expand Up @@ -213,7 +222,7 @@ async function main() {
try {
const browser = createBrowserHelpers(driver, popupUrl);
const selectedScenarios = scenarios
.flatMap((item) => ['light', 'dark'].map((theme) => ({ ...item, theme })))
.flatMap(item => ['light', 'dark'].map(theme => ({ ...item, theme })))
.filter(({ area, name, theme }) => !FILTER || `${area}-${name}-${theme}`.includes(FILTER));

if (selectedScenarios.length === 0) {
Expand All @@ -236,7 +245,7 @@ async function main() {
}

function createBrowserHelpers(driver, popupUrl) {
const elements = async (selector) => driver.findElements(By.css(selector));
const elements = async selector => driver.findElements(By.css(selector));
const element = async (selector, index = 0) => {
const matches = await elements(selector);
if (!matches[index]) {
Expand Down Expand Up @@ -266,21 +275,21 @@ function createBrowserHelpers(driver, popupUrl) {
await waitUntil(() => visible(selector, index), `${selector} to become visible`);
await (await element(selector, index)).sendKeys(Key.TAB);
};
const waitText = async (text) => {
const waitText = async text => {
await waitUntil(async () => {
const body = await driver.findElement(By.css('body'));
return (await body.getText()).includes(text);
}, `text "${text}"`);
};
const clickMenuItem = async (text) => {
const clickMenuItem = async text => {
const xpath = `//*[@role="menuitem" and contains(normalize-space(.), "${text}")]`;
await waitUntil(async () => {
const matches = await driver.findElements(By.xpath(xpath));
return matches.length > 0 && await matches[0].isDisplayed();
return matches.length > 0 && (await matches[0].isDisplayed());
}, `menu item "${text}"`);
await (await driver.findElements(By.xpath(xpath)))[0].click();
};
const clickTab = async (text) => {
const clickTab = async text => {
const xpath = `//*[@role="tab" and contains(normalize-space(.), "${text}")]`;
await waitUntil(async () => (await driver.findElements(By.xpath(xpath))).length > 0, `tab "${text}"`);
await (await driver.findElements(By.xpath(xpath)))[0].click();
Expand Down Expand Up @@ -312,6 +321,15 @@ function createBrowserHelpers(driver, popupUrl) {
click,
clickMenuItem,
fill,
openOptions: async () => {
const optionsUrl = popupUrl.replace(/popup\.html$/, 'options.html');
await driver.get(optionsUrl);
await waitUntil(() => visible(selectors.settingsPage), 'settings page');
await waitUntil(async () => {
const className = await driver.findElement(By.css('body')).getAttribute('class');
return className.includes('light') || className.includes('dark');
}, 'options theme');
},
removeAllCookies: async () => {
await click(selectors.removeAllCookiesButton);
},
Expand All @@ -333,7 +351,7 @@ function createBrowserHelpers(driver, popupUrl) {
await driver.navigate().refresh();
await waitUntil(() => visible(selectors.headerNameInput), 'popup to reload');
},
setTheme: async (theme) => {
setTheme: async theme => {
await click(selectors.themeToggle);
await clickMenuItem(theme === 'light' ? 'Light' : 'Dark');
await waitUntil(
Expand Down Expand Up @@ -382,7 +400,7 @@ async function assertScreenshot(driver, snapshotName) {
}
}

main().catch((error) => {
main().catch(error => {
console.error(error);
process.exitCode = 1;
});
23 changes: 4 additions & 19 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,14 @@ import '@cloud-ru/ds-figma-variables/build/css/tokens.css';

import './styles.css';

import { useUnit } from 'effector-react';
import { useEffect, useRef } from 'react';

import { BRAND, DENSITY, PLATFORM, RootThemeProvider } from '@cloud-ru/ds-theme';

import { $colorScheme } from '#entities/themeMode/model';
import { MainPage } from '#pages/main';
import { initApp } from '#shared/model';

export function App() {
const [handleInitApp, colorScheme] = useUnit([initApp, $colorScheme]);
const bodyRef = useRef<HTMLElement>(document.body);

useEffect(() => {
handleInitApp();
}, [handleInitApp]);
import { ThemeRoot } from './ThemeRoot';

export function App() {
return (
<RootThemeProvider
rootRef={bodyRef}
value={{ colorScheme, brand: BRAND.SnackUI, platform: PLATFORM.WebDesktop, density: DENSITY.Compact }}
>
<ThemeRoot>
<MainPage />
</RootThemeProvider>
</ThemeRoot>
);
}
21 changes: 21 additions & 0 deletions src/app/OptionsApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import '@cloud-ru/ds-figma-variables/build/css/tokens.css';

import './styles.css';
import './options.css';

import { Settings } from '#widgets/settings';

import * as S from './options.styled';
import { ThemeRoot } from './ThemeRoot';

export function OptionsApp() {
return (
<ThemeRoot>
<S.Page>
<S.Panel>
<Settings />
</S.Panel>
</S.Page>
</ThemeRoot>
);
}
29 changes: 29 additions & 0 deletions src/app/ThemeRoot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useUnit } from 'effector-react';
import { ReactNode, useEffect, useRef } from 'react';

import { BRAND, DENSITY, PLATFORM, RootThemeProvider } from '@cloud-ru/ds-theme';

import { $colorScheme } from '#entities/themeMode/model';
import { initApp } from '#shared/model';

type ThemeRootProps = {
children: ReactNode;
};

export function ThemeRoot({ children }: ThemeRootProps) {
const [handleInitApp, colorScheme] = useUnit([initApp, $colorScheme]);
const bodyRef = useRef<HTMLElement>(document.body);

useEffect(() => {
handleInitApp();
}, [handleInitApp]);

return (
<RootThemeProvider
rootRef={bodyRef}
value={{ colorScheme, brand: BRAND.SnackUI, platform: PLATFORM.WebDesktop, density: DENSITY.Compact }}
>
{children}
</RootThemeProvider>
);
}
6 changes: 6 additions & 0 deletions src/app/options.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
body.options-page,
body.options-page #app-container {
width: 100%;
height: auto;
min-height: 100vh;
}
17 changes: 17 additions & 0 deletions src/app/options.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from '@emotion/styled';

import { themeVars } from '@cloud-ru/ds-figma-variables';

export const Page = styled.main`
display: flex;
justify-content: center;
min-height: 100vh;
background: ${themeVars.sn.theme.color.neutral.background1Level};
color: ${themeVars.sn.theme.color.available.version.textMain};
`;

export const Panel = styled.div`
width: 100%;
max-width: 480px;
padding: 8px 0 32px;
`;
Loading
Loading