Skip to content

Commit

Permalink
js agent support
Browse files Browse the repository at this point in the history
  • Loading branch information
pavyarov authored and pavyarov committed Aug 4, 2020
1 parent 8ce83ee commit ea1094c
Show file tree
Hide file tree
Showing 50 changed files with 1,542 additions and 1,109 deletions.
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@drill4j/browser-extension",
"version": "0.3.14",
"version": "0.3.15",
"license": "Apache-2.0",
"scripts": {
"build": "NODE_ENV=production webpack",
Expand All @@ -9,18 +9,22 @@
"lint": "eslint . --ext .ts,.tsx"
},
"dependencies": {
"@drill4j/ui-kit": "^0.1.13",
"@drill4j/ui-kit": "^0.1.18",
"@redneckz/react-bem-helper": "^2.0.3",
"@redneckz/react-dispatcher": "^0.0.6",
"@types/axios": "^0.14.0",
"@types/chrome": "^0.0.117",
"@types/node": "^13.13.2",
"@types/react": "^16.9.34",
"@types/react-dom": "^16.9.6",
"@types/react-router-dom": "^5.1.4",
"axios": "^0.19.2",
"final-form": "^4.20.1",
"nanoid": "^2.1.11",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-draggable": "^4.3.1",
"react-final-form": "^6.5.1",
"react-router-dom": "^5.1.2",
"rxjs": "^6.5.5",
"webextension-polyfill-ts": "^0.14.0"
Expand Down
165 changes: 159 additions & 6 deletions src/background.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/* eslint-disable no-undef */
import { browser, WebRequest } from 'webextension-polyfill-ts';
import nanoid from 'nanoid';

import { AgentConfig } from 'types/agent-config';
import { DEBUGGER_VERSION } from './common/constants';
import { DomainConfig } from './types/domain-config';

let configMap: { [host: string]: AgentConfig } = {};
let configMap: { domains?: { [host: string]: DomainConfig } } = {};

browser.storage.local.get().then((value) => {
if (value) {
Expand All @@ -18,7 +21,7 @@ browser.storage.onChanged.addListener(() => {

function requestInteceptor({ requestHeaders = [], initiator = '' }: WebRequest.OnBeforeSendHeadersDetailsType & { initiator?: string}) {
const requestHost = getHost(initiator);
const { sessionId, testName, isActive } = configMap[requestHost] || {};
const { sessionId = '', testName = '', isActive = false } = configMap.domains ? configMap.domains[requestHost] || {} : {};
if (isActive) {
requestHeaders.push({ name: 'drill-session-id', value: sessionId });
requestHeaders.push({ name: 'drill-test-name', value: testName });
Expand Down Expand Up @@ -53,16 +56,17 @@ function responseInterceptor({ responseHeaders = [], initiator = '' }: WebReques
}

async function storeConfig(host: string, config: { [key: string]: string | undefined }) {
const { [host]: currentConfig } = await browser.storage.local.get([host]);
const { domains } = await browser.storage.local.get('domains');
const { [host]: currentConfig } = domains || {};

if (!currentConfig || !compareConfigs(currentConfig, config)) {
browser.storage.local.set({
[host]: { ...config },
domains: { ...domains, [host]: { ...config } },
});
}
}

function compareConfigs({ drillAgentId, drillGroupId, drillAdminUrl }: AgentConfig, newConfig: AgentConfig) {
function compareConfigs({ drillAgentId, drillGroupId, drillAdminUrl }: DomainConfig, newConfig: DomainConfig) {
const { drillAgentId: agentId, drillGroupId: groupId, drillAdminUrl: adminUrl } = newConfig;
return (drillAgentId === agentId || drillGroupId === groupId) && drillAdminUrl === adminUrl;
}
Expand All @@ -71,3 +75,152 @@ const toCamel = (srt: string) => srt.replace(/([-_][a-z])/ig, ($match) => $match
.replace('-', ''));

const getHost = (url: string) => new URL(url).host;

browser.runtime.onMessage.addListener((request: any, sender: any) => {
if (request.action === 'START_TEST') {
startTest(sender.tab);
}

if (request.action === 'FINISH_TEST') {
return Promise.resolve(stopTest(sender.tab, request.testName));
}

return Promise.resolve(true);
});

// const sendData = (endpoint: string, data: object, callback?: () => void) => {
// fetch(`${BACKEND_URL}/${endpoint}`, {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json;charset=UTF-8',
// },
// body: JSON.stringify(data),
// }).then(callback);
// };

const asPromised = (block: any) => new Promise((resolve, reject) => {
block((...results: any[]) => {
if (browser.runtime.lastError) {
reject(browser.extension.lastError);
} else {
resolve(...results);
}
});
});

const devTools = {
attach(target: any) {
return asPromised((callback: any) => {
chrome.debugger.attach(target, DEBUGGER_VERSION, callback);
});
},

sendCommand(target: any, method: any, params: any) {
return asPromised((callback: any) => {
chrome.debugger.sendCommand(target, method, params, callback);
});
},

detach(target: any) {
return asPromised((callback: any) => {
chrome.debugger.detach(target, callback);
});
},
};

const storage = {
set(items: object) {
return asPromised(() => {
browser.storage.local.set(items);
});
},

get(keys: string | string[]) {
return asPromised(() => {
browser.storage.local.get(keys);
});
},

remove(keys: string[]) {
return asPromised(() => {
browser.storage.local.remove(keys);
});
},
};

const scriptSources: any = {};

const startTest = async (tab: any) => {
const target = {
tabId: tab.id,
};

await devTools.attach(target);

await devTools.sendCommand(target, 'Profiler.enable', {});
await devTools.sendCommand(target, 'Profiler.startPreciseCoverage', {
callCount: false,
detailed: true,
});

chrome.debugger.onEvent.addListener(async (source, method, params) => {
if (method !== 'Debugger.scriptParsed') {
return;
}

const { url, scriptId } = params as { url: string; scriptId: string };

if (!url || url.startsWith('chrome-extension:') || url.includes('google-analytics.com')) {
return;
}

const rawScriptSource: any = await devTools.sendCommand(target, 'Debugger.getScriptSource', { scriptId });

scriptSources[url] = {
id: scriptId,
source: rawScriptSource.scriptSource,
};
});

await devTools.sendCommand(target, 'Debugger.enable', {});
await devTools.sendCommand(target, 'Debugger.setSkipAllPauses', { skip: true });

const sessionId = nanoid();
await storage.set({ sessionId });

// await sendData('start-session', {
// sessionId,
// });
};

const stopTest = async (tab: any, testName: any) => {
const target = {
tabId: tab.id,
};

const data: any = await devTools.sendCommand(target, 'Profiler.takePreciseCoverage', {});
await devTools.sendCommand(target, 'Profiler.stopPreciseCoverage', {});
await devTools.sendCommand(target, 'Profiler.disable', {});
await devTools.sendCommand(target, 'Debugger.disable', {});

await devTools.detach(target);

// await sendData('coverage', {
// runUuid: nanoid(),
// test: {
// name: testName,
// type: 'manual',
// },
// coverage: data.result,
// scriptSources,
// }, async () => {
// const { sessionId } = await storage.get('sessionId') as any;
// await sendData('finish-session', {
// sessionId,
// });
// });

return { coverage: data.result, scriptSources };

// scriptSources = {};
};
2 changes: 0 additions & 2 deletions src/common/constants/eventTypes.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/common/constants/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEBUGGER_VERSION = '1.3';
2 changes: 1 addition & 1 deletion src/common/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { GLOBAL, LOCAL } from './eventTypes';
export { TOKEN_HEADER, TOKEN_KEY } from './connection';
export { DEBUGGER_VERSION } from './global';
1 change: 0 additions & 1 deletion src/common/constants/messages.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/content-script/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { reducer, savePosition, setExpanded } from './reducer';
import { Sidebar } from './sidebar';
import { ManualTestingPage, TestToCodePage } from './pages';


export const App = () => {
const [state, dispatch] = React.useReducer(reducer, { expanded: false });
useDispatcher(state, dispatch);
Expand Down
1 change: 1 addition & 0 deletions src/content-script/pages/manual-testing-page/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { startGroupSession } from './start-group-session';
export { startAgentSession } from './start-agent-session';
export { startSession } from './start-session';
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import axios from 'axios';
import { browser } from 'webextension-polyfill-ts';

import { AgentConfig } from '../../../../types/agent-config';
import { DomainConfig } from '../../../../types/domain-config';

export async function startAgentSession(activeTab: string, testName: string, config: AgentConfig) {
export async function startAgentSession(activeTab: string, testName: string, config: DomainConfig) {
const { drillAgentId } = config;
const { domains } = await browser.storage.local.get('domains') || {};
const { data } = await axios.post(`/agents/${drillAgentId}/plugins/test2code/dispatch-action`, {
type: 'START',
payload: { testType: 'MANUAL' },
});
const { data: { payload: { sessionId } } } = data;

browser.storage.local.set({
[activeTab]: {
...config, testName, isActive: true, sessionId, timerStart: Date.now(),
domains: {
...domains,
[activeTab]: {
...config, testName, isActive: true, sessionId, timerStart: Date.now(),
},
},
});
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import axios from 'axios';
import { browser } from 'webextension-polyfill-ts';

import { AgentConfig } from '../../../../types/agent-config';
import { DomainConfig } from '../../../../types/domain-config';

export async function startGroupSession(activeTab: string, testName: string, config: AgentConfig) {
export async function startGroupSession(activeTab: string, testName: string, config: DomainConfig) {
const { drillGroupId } = config;
const { domains } = await browser.storage.local.get('domains') || {};
const { data: [response] } = await axios.post(`/service-groups/${drillGroupId}/plugins/test2code/dispatch-action`, {
type: 'START',
payload: { testType: 'MANUAL' },
});
const { data: { payload: { sessionId } } } = response;

browser.storage.local.set({
[activeTab]: {
...config, testName, isActive: true, sessionId, timerStart: Date.now(),
domains: {
...domains,
[activeTab]: {
...config, testName, isActive: true, sessionId, timerStart: Date.now(),
},
},
});
}
45 changes: 45 additions & 0 deletions src/content-script/pages/manual-testing-page/api/start-session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import axios from 'axios';
import { browser } from 'webextension-polyfill-ts';
import nanoid from 'nanoid';

import { DomainConfig } from '../../../../types/domain-config';

export async function startSession(activeTab: string, testName: string, config: DomainConfig) {
const { drillAgentId, drillAgentType = 'Java', drillAdminUrl } = config;
const { domains } = await browser.storage.local.get('domains') || {};

if (drillAgentType === 'JS') {
const connection = axios.create({ baseURL: `http://${drillAdminUrl}` });
const sessionId = nanoid();

browser.runtime.sendMessage({ action: 'START_TEST', testName });

await connection.post(`/agents/${drillAgentId}/plugins/test2code/sessions/${sessionId}`);

browser.runtime.sendMessage({ action: 'START_TEST' });

browser.storage.local.set({
domains: {
...domains,
[activeTab]: {
...config, testName, isActive: true, sessionId, timerStart: Date.now(),
},
},
});
} else {
const { data } = await axios.post(`/agents/${drillAgentId}/plugins/test2code/dispatch-action`, {
type: 'START',
payload: { testType: 'MANUAL', isRealtime: true },
});
const { data: { payload: { sessionId } } } = data;

browser.storage.local.set({
domains: {
...domains,
[activeTab]: {
...config, testName, isActive: true, sessionId, timerStart: Date.now(),
},
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const FinishRecording = finishRecording(({ className }: Props) => {
} = {},
}: any = useActiveScope(drillAdminUrl) || {};


const seconds = (`0${Math.floor((Date.now() - timerStart) / 1000) % 60}`).slice(-2);
const minutes = (`0${Math.floor((Date.now() - timerStart) / 60000) % 60}`).slice(-2);
const hours = (`0${Math.floor((Date.now() - timerStart) / 3600000)}`).slice(-2);
Expand Down
Loading

0 comments on commit ea1094c

Please sign in to comment.