refactor(frontend): remove deprecated types
This commit is contained in:
parent
d081873ca5
commit
cbbe26a3d5
12 changed files with 1 additions and 1037 deletions
|
|
@ -7,12 +7,8 @@ import issues from './issues';
|
||||||
import assignments from './assignments';
|
import assignments from './assignments';
|
||||||
import target from './target';
|
import target from './target';
|
||||||
import targetCustom from './targetCustom';
|
import targetCustom from './targetCustom';
|
||||||
import runs from './runs';
|
|
||||||
import filters from './filters';
|
import filters from './filters';
|
||||||
import funnelFilters from './funnelFilters';
|
import funnelFilters from './funnelFilters';
|
||||||
import tests from './tests';
|
|
||||||
import steps from './steps';
|
|
||||||
import schedules from './schedules';
|
|
||||||
import events from './events';
|
import events from './events';
|
||||||
import environments from './environments';
|
import environments from './environments';
|
||||||
import variables from './variables';
|
import variables from './variables';
|
||||||
|
|
@ -46,12 +42,9 @@ export default combineReducers({
|
||||||
assignments,
|
assignments,
|
||||||
target,
|
target,
|
||||||
targetCustom,
|
targetCustom,
|
||||||
runs,
|
|
||||||
filters,
|
filters,
|
||||||
funnelFilters,
|
funnelFilters,
|
||||||
tests,
|
|
||||||
steps,
|
|
||||||
schedules,
|
|
||||||
events,
|
events,
|
||||||
environments,
|
environments,
|
||||||
variables,
|
variables,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
import Run from 'Types/run';
|
|
||||||
import crudDuckGenerator from './tools/crudDuck';
|
|
||||||
|
|
||||||
const crudDuck = crudDuckGenerator('run', Run);
|
|
||||||
export const { fetchList, fetch, init, edit, save, remove } = crudDuck.actions;
|
|
||||||
|
|
||||||
export default crudDuck.reducer;
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
import Schedule from 'Types/schedule';
|
|
||||||
import crudDuckGenerator from './tools/crudDuck';
|
|
||||||
|
|
||||||
const crudDuck = crudDuckGenerator('scheduler', Schedule);
|
|
||||||
export const { fetchList, fetch, init, edit, remove } = crudDuck.actions;
|
|
||||||
|
|
||||||
export function save(instance) { // TODO: fix the crudDuckGenerator
|
|
||||||
return {
|
|
||||||
types: crudDuck.actionTypes.SAVE.toArray(),
|
|
||||||
call: client => client.post(`/schedulers${!!instance.schedulerId ? '/' + instance.schedulerId : '' }`, instance),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default crudDuck.reducer;
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
import { List, Map } from 'immutable';
|
|
||||||
import { RequestTypes } from 'Duck/requestStateCreator';
|
|
||||||
import Step from 'Types/step';
|
|
||||||
import Event from 'Types/filter/event';
|
|
||||||
import { getRE } from 'App/utils';
|
|
||||||
import Test from 'Types/appTest';
|
|
||||||
import { countries } from 'App/constants';
|
|
||||||
import { KEYS } from 'Types/filter/customFilter';
|
|
||||||
|
|
||||||
const countryOptions = Object.keys(countries).map(c => ({filterKey: KEYS.USER_COUNTRY, label: KEYS.USER_COUNTRY, type: KEYS.USER_COUNTRY, value: c, actualValue: countries[c], isFilter: true }));
|
|
||||||
|
|
||||||
const INIT = 'steps/INIT';
|
|
||||||
const EDIT = 'steps/EDIT';
|
|
||||||
|
|
||||||
const SET_TEST = 'steps/SET_TEST';
|
|
||||||
const FETCH_LIST = new RequestTypes('steps/FETCH_LIST');
|
|
||||||
|
|
||||||
const initialState = Map({
|
|
||||||
list: List(),
|
|
||||||
test: Test(),
|
|
||||||
instance: Step(),
|
|
||||||
editingIndex: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
const reducer = (state = initialState, action = {}) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case FETCH_LIST.SUCCESS: {
|
|
||||||
return state.set('list', List(action.data).map(i => {
|
|
||||||
const type = i.type === 'navigate' ? i.type : 'location';
|
|
||||||
return {...i, type: type.toUpperCase()}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
case INIT:
|
|
||||||
return state
|
|
||||||
.set('instance', Step(action.instance))
|
|
||||||
.set('editingIndex', action.index)
|
|
||||||
.set('test', Test());
|
|
||||||
case EDIT:
|
|
||||||
return state.mergeIn([ 'instance' ], action.instance);
|
|
||||||
case SET_TEST:
|
|
||||||
return state.set('test', Test(action.test));
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default reducer;
|
|
||||||
|
|
||||||
export function init(instance, index) {
|
|
||||||
return {
|
|
||||||
type: INIT,
|
|
||||||
instance,
|
|
||||||
index,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function edit(instance) {
|
|
||||||
return {
|
|
||||||
type: EDIT,
|
|
||||||
instance,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setTest(test) {
|
|
||||||
return {
|
|
||||||
type: SET_TEST,
|
|
||||||
test,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function fetchList(params) {
|
|
||||||
return {
|
|
||||||
types: FETCH_LIST.toArray(),
|
|
||||||
call: client => client.get('/tests/steps/search', params),
|
|
||||||
params,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,118 +0,0 @@
|
||||||
import { Map } from 'immutable';
|
|
||||||
import Test from 'Types/appTest';
|
|
||||||
import Run, { RUNNING, STOPPED } from 'Types/run';
|
|
||||||
import requestDuckGenerator, { RequestTypes } from 'Duck/tools/requestDuck';
|
|
||||||
import { reduceDucks } from 'Duck/tools';
|
|
||||||
|
|
||||||
const GEN_TEST = new RequestTypes('tests/GEN_TEST');
|
|
||||||
const RUN_TEST = new RequestTypes('tests/RUN_TEST');
|
|
||||||
const STOP_RUN = new RequestTypes('tests/STOP_RUN');
|
|
||||||
const STOP_ALL_RUNS = new RequestTypes('tests/STOP_ALL_RUNS');
|
|
||||||
const CHECK_RUN = new RequestTypes('tests/CHECK_RUN');
|
|
||||||
const RESET_ERRORS = 'tests/RESET_ERRORS';
|
|
||||||
|
|
||||||
const updateRunInTest = run => (test) => {
|
|
||||||
const runIndex = test.runHistory
|
|
||||||
.findLastIndex(({ runId }) => run.runId === runId);
|
|
||||||
return runIndex === -1
|
|
||||||
? test.update('runHistory', list => list.push(run))
|
|
||||||
: test.mergeIn([ 'runHistory', runIndex ], run);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateRun = (state, testId, run) => {
|
|
||||||
const testIndex = state.get('list').findIndex(test => test.testId === testId);
|
|
||||||
if (testIndex === -1) return state;
|
|
||||||
const updater = updateRunInTest(run);
|
|
||||||
return state
|
|
||||||
.updateIn([ 'list', testIndex ], updater)
|
|
||||||
.updateIn([ 'instance' ], test => (test.testId === testId
|
|
||||||
? updater(test)
|
|
||||||
: test));
|
|
||||||
};
|
|
||||||
|
|
||||||
const initialState = Map({});
|
|
||||||
|
|
||||||
const reducer = (state = initialState, action = {}) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case GEN_TEST.SUCCESS:
|
|
||||||
return state.set('instance', Test(action.data).set('generated', true));
|
|
||||||
case RUN_TEST.SUCCESS: {
|
|
||||||
const test = state.get('list').find(({ testId }) => testId === action.testId);
|
|
||||||
const run = Run({
|
|
||||||
runId: action.data.id, state: RUNNING, testId: action.testId, name: test.name
|
|
||||||
});
|
|
||||||
return updateRun(state, action.testId, run);
|
|
||||||
}
|
|
||||||
case STOP_RUN.SUCCESS: {
|
|
||||||
const { testId, runId } = action;
|
|
||||||
return updateRun(state, testId, { runId, state: STOPPED });
|
|
||||||
}
|
|
||||||
case STOP_ALL_RUNS.SUCCESS:
|
|
||||||
return state.update('list', list => list.map(test => {
|
|
||||||
test.runHistory.map(run => run.state === RUNNING ? run.set('state', STOPPED) : run.state);
|
|
||||||
return test;
|
|
||||||
})).setIn(['runRequest', 'errors'], null);
|
|
||||||
case CHECK_RUN.SUCCESS:
|
|
||||||
return updateRun(state, action.testId, Run(action.data));
|
|
||||||
case RESET_ERRORS:
|
|
||||||
return state.setIn(['runRequest', 'errors'], null);
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
};
|
|
||||||
|
|
||||||
const requestDuck = requestDuckGenerator({
|
|
||||||
runRequest: RUN_TEST,
|
|
||||||
stopRunRequest: STOP_RUN,
|
|
||||||
stopAllRunsRequest: STOP_ALL_RUNS,
|
|
||||||
genTestRequest: GEN_TEST,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default reduceDucks({ reducer, initialState }, requestDuck);
|
|
||||||
|
|
||||||
|
|
||||||
export function generateTest(sessionId, params) {
|
|
||||||
return {
|
|
||||||
types: GEN_TEST.toArray(),
|
|
||||||
call: client => client.post(`/sessions/${ sessionId }/gentest`, params),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function runTest(testId, params) {
|
|
||||||
return {
|
|
||||||
testId,
|
|
||||||
types: RUN_TEST.toArray(),
|
|
||||||
call: client => client.post(`/tests/${ testId }/execute`, params),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopRun(testId, runId) {
|
|
||||||
return {
|
|
||||||
runId,
|
|
||||||
testId,
|
|
||||||
types: STOP_RUN.toArray(),
|
|
||||||
call: client => client.get(`/runs/${ runId }/stop`),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stopAllRuns() {
|
|
||||||
return {
|
|
||||||
types: STOP_ALL_RUNS.toArray(),
|
|
||||||
call: client => client.get(`/runs/all/stop`),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resetErrors() {
|
|
||||||
return {
|
|
||||||
type: RESET_ERRORS,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkRun(testId, runId) {
|
|
||||||
return {
|
|
||||||
runId,
|
|
||||||
testId,
|
|
||||||
types: CHECK_RUN.toArray(),
|
|
||||||
call: client => client.get(`/runs/${ runId }`),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
import fromJS from './run';
|
|
||||||
|
|
||||||
export * from './run';
|
|
||||||
export default fromJS;
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
import { Record, List, Map } from 'immutable';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import Environment from 'Types/environment';
|
|
||||||
import stepFromJS from './step';
|
|
||||||
import seleniumStepFromJS from './seleniumStep';
|
|
||||||
import Resource from '../session/resource';
|
|
||||||
|
|
||||||
export const NOT_FETCHED = undefined;
|
|
||||||
export const QUEUED = 'queued';
|
|
||||||
export const INITIALIZING = 'initializing';
|
|
||||||
export const RUNNING = 'running';
|
|
||||||
export const COMPLETED = 'completed';
|
|
||||||
export const PASSED = 'passed';
|
|
||||||
export const FAILED = 'failed';
|
|
||||||
export const STOPPED = 'stopped';
|
|
||||||
export const CRASHED = 'crashed';
|
|
||||||
export const EXPIRED = 'expired';
|
|
||||||
|
|
||||||
export const STATUS = {
|
|
||||||
NOT_FETCHED,
|
|
||||||
QUEUED,
|
|
||||||
INITIALIZING,
|
|
||||||
RUNNING,
|
|
||||||
COMPLETED,
|
|
||||||
PASSED,
|
|
||||||
FAILED,
|
|
||||||
STOPPED,
|
|
||||||
CRASHED,
|
|
||||||
EXPIRED,
|
|
||||||
}
|
|
||||||
|
|
||||||
class Run extends Record({
|
|
||||||
runId: undefined,
|
|
||||||
testId: undefined,
|
|
||||||
name: '',
|
|
||||||
tags: List(),
|
|
||||||
environment: Environment(),
|
|
||||||
scheduled: false,
|
|
||||||
schedulerId: undefined,
|
|
||||||
browser: undefined,
|
|
||||||
sessionId: undefined,
|
|
||||||
startedAt: undefined,
|
|
||||||
url_video: undefined,
|
|
||||||
finishedAt: undefined,
|
|
||||||
steps: List(),
|
|
||||||
resources: [],
|
|
||||||
seleniumSteps: List(),
|
|
||||||
url_browser_logs: undefined,
|
|
||||||
url_logs: undefined,
|
|
||||||
url_selenium_project: undefined,
|
|
||||||
sourceCode: undefined,
|
|
||||||
screenshotUrl: undefined,
|
|
||||||
clientId: undefined,
|
|
||||||
state: NOT_FETCHED,
|
|
||||||
baseRunId: undefined,
|
|
||||||
lastExecutedString: undefined,
|
|
||||||
durationString: undefined,
|
|
||||||
hour: undefined, // TODO: fine API
|
|
||||||
day: undefined,
|
|
||||||
location: undefined,
|
|
||||||
deviceType: undefined,
|
|
||||||
advancedOptions: undefined,
|
|
||||||
harfile: undefined,
|
|
||||||
lighthouseHtmlFile: undefined,
|
|
||||||
resultsFile: undefined,
|
|
||||||
lighthouseJsonFile: undefined,
|
|
||||||
totalStepsCount: undefined,
|
|
||||||
auditsPerformance: Map(),
|
|
||||||
auditsAd: Map(),
|
|
||||||
transferredSize: undefined,
|
|
||||||
resourcesSize: undefined,
|
|
||||||
domBuildingTime: undefined,
|
|
||||||
domContentLoadedTime: undefined,
|
|
||||||
loadTime: undefined,
|
|
||||||
starter: undefined,
|
|
||||||
// {
|
|
||||||
// "id": '',
|
|
||||||
// "title": '',
|
|
||||||
// "description": '',
|
|
||||||
// "score": 0,
|
|
||||||
// "scoreDisplayMode": '',
|
|
||||||
// "numericValue": 0,
|
|
||||||
// "numericUnit": '',
|
|
||||||
// "displayValue": ''
|
|
||||||
// }
|
|
||||||
}) {
|
|
||||||
idKey = 'runId';
|
|
||||||
isRunning() {
|
|
||||||
return this.state === RUNNING;
|
|
||||||
}
|
|
||||||
isQueued() {
|
|
||||||
return this.state === QUEUED;
|
|
||||||
}
|
|
||||||
isPassed() {
|
|
||||||
return this.state === PASSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line complexity
|
|
||||||
function fromJS(run = {}) {
|
|
||||||
if (run instanceof Run) return run;
|
|
||||||
|
|
||||||
const startedAt = run.startedAt && DateTime.fromMillis(run.startedAt);
|
|
||||||
const finishedAt = run.finishedAt && DateTime.fromMillis(run.finishedAt);
|
|
||||||
let durationString;
|
|
||||||
let lastExecutedString;
|
|
||||||
if (run.state === 'running') {
|
|
||||||
durationString = 'Running...';
|
|
||||||
lastExecutedString = 'Now';
|
|
||||||
} else if (startedAt && finishedAt) {
|
|
||||||
const _duration = Math.floor(finishedAt - startedAt);
|
|
||||||
if (_duration > 10000) {
|
|
||||||
const min = Math.floor(_duration / 60000);
|
|
||||||
durationString = `${ min < 1 ? 1 : min } min`;
|
|
||||||
} else {
|
|
||||||
durationString = `${ Math.floor(_duration / 1000) } secs`;
|
|
||||||
}
|
|
||||||
const diff = startedAt.diffNow([ 'days', 'hours', 'minutes', 'seconds' ]).negate();
|
|
||||||
if (diff.days > 0) {
|
|
||||||
lastExecutedString = `${ Math.round(diff.days) } day${ diff.days > 1 ? 's' : '' } ago`;
|
|
||||||
} else if (diff.hours > 0) {
|
|
||||||
lastExecutedString = `${ Math.round(diff.hours) } hrs ago`;
|
|
||||||
} else if (diff.minutes > 0) {
|
|
||||||
lastExecutedString = `${ Math.round(diff.minutes) } min ago`;
|
|
||||||
} else {
|
|
||||||
lastExecutedString = `${ Math.round(diff.seconds) } sec ago`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const steps = List(run.steps).map(stepFromJS);
|
|
||||||
const seleniumSteps = List(run.seleniumSteps).map(seleniumStepFromJS);
|
|
||||||
const tags = List(run.tags);
|
|
||||||
const environment = Environment(run.environment);
|
|
||||||
|
|
||||||
let resources = List(run.network)
|
|
||||||
.map(i => Resource({
|
|
||||||
...i,
|
|
||||||
// success: 1,
|
|
||||||
// time: i.timestamp,
|
|
||||||
// type: 'xhr',
|
|
||||||
// headerSize: 1200,
|
|
||||||
// timings: {},
|
|
||||||
}));
|
|
||||||
const firstResourceTime = resources.map(r => r.time).reduce((a,b)=>Math.min(a,b), Number.MAX_SAFE_INTEGER);
|
|
||||||
resources = resources
|
|
||||||
.map(r => r.set("time", r.time - firstResourceTime))
|
|
||||||
.sort((r1, r2) => r1.time - r2.time).toArray()
|
|
||||||
|
|
||||||
const screenshotUrl = run.screenshot_url ||
|
|
||||||
seleniumSteps.find(({ screenshotUrl }) => !!screenshotUrl, null, {}).screenshotUrl;
|
|
||||||
|
|
||||||
const state = run.state === 'completed' ? PASSED : run.state;
|
|
||||||
const networkOverview = run.networkOverview || {};
|
|
||||||
|
|
||||||
return new Run({
|
|
||||||
...run,
|
|
||||||
startedAt,
|
|
||||||
finishedAt,
|
|
||||||
durationString,
|
|
||||||
lastExecutedString,
|
|
||||||
steps,
|
|
||||||
resources,
|
|
||||||
seleniumSteps,
|
|
||||||
tags,
|
|
||||||
environment,
|
|
||||||
screenshotUrl,
|
|
||||||
state,
|
|
||||||
deviceType: run.device || run.deviceType,
|
|
||||||
auditsPerformance: run.lighthouseJson && run.lighthouseJson.performance,
|
|
||||||
auditsAd: run.lighthouseJson && run.lighthouseJson.ad,
|
|
||||||
transferredSize: networkOverview.transferredSize,
|
|
||||||
resourcesSize: networkOverview.resourcesSize,
|
|
||||||
domBuildingTime: networkOverview.domBuildingTime,
|
|
||||||
domContentLoadedTime: networkOverview.domContentLoadedTime,
|
|
||||||
loadTime: networkOverview.loadTime,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Run.prototype.exists = function () {
|
|
||||||
return this.runId !== undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default fromJS;
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import { Record, List } from 'immutable';
|
|
||||||
import { DateTime, Duration } from 'luxon';
|
|
||||||
|
|
||||||
const Step = Record({
|
|
||||||
duration: undefined,
|
|
||||||
startedAt: undefined,
|
|
||||||
label: undefined,
|
|
||||||
input: undefined,
|
|
||||||
info: undefined,
|
|
||||||
order: undefined,
|
|
||||||
screenshotUrl: undefined,
|
|
||||||
steps: List(),
|
|
||||||
});
|
|
||||||
|
|
||||||
function fromJS(step = {}) {
|
|
||||||
const startedAt = step.startedAt && DateTime.fromMillis(step.startedAt * 1000);
|
|
||||||
const duration = step.executionTime && Duration.fromMillis(step.executionTime);
|
|
||||||
const steps = List(step.steps).map(Step);
|
|
||||||
const screenshotUrl = step.screenshot_url;
|
|
||||||
return new Step({
|
|
||||||
...step,
|
|
||||||
steps,
|
|
||||||
startedAt,
|
|
||||||
duration,
|
|
||||||
screenshotUrl,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default fromJS;
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import { Record, List } from 'immutable';
|
|
||||||
import { DateTime, Duration } from 'luxon';
|
|
||||||
|
|
||||||
const Step = Record({
|
|
||||||
duration: undefined,
|
|
||||||
startedAt: undefined,
|
|
||||||
label: undefined,
|
|
||||||
input: undefined,
|
|
||||||
info: undefined,
|
|
||||||
order: undefined,
|
|
||||||
status: undefined,
|
|
||||||
title: undefined,
|
|
||||||
screenshotUrl: undefined,
|
|
||||||
steps: List(),
|
|
||||||
});
|
|
||||||
|
|
||||||
function fromJS(step = {}) {
|
|
||||||
const startedAt = step.startedAt && DateTime.fromMillis(step.startedAt);
|
|
||||||
const duration = step.executionTime && Duration.fromMillis(step.executionTime);
|
|
||||||
const steps = List(step.steps).map(Step);
|
|
||||||
const screenshotUrl = step.screenshot;
|
|
||||||
return new Step({
|
|
||||||
...step,
|
|
||||||
steps,
|
|
||||||
startedAt,
|
|
||||||
duration,
|
|
||||||
screenshotUrl,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default fromJS;
|
|
||||||
|
|
@ -1,228 +0,0 @@
|
||||||
import { Record, List, Map } from 'immutable';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import {
|
|
||||||
CHANNEL,
|
|
||||||
DAYS,
|
|
||||||
HOURS,
|
|
||||||
EMAIL,
|
|
||||||
SLACK,
|
|
||||||
WEBHOOK
|
|
||||||
} from 'App/constants/schedule';
|
|
||||||
// import runFromJS from './run';
|
|
||||||
import { validateEmail } from 'App/validate';
|
|
||||||
|
|
||||||
export const DEFAULT_ENV_VALUE = '_';
|
|
||||||
const Schedule = Record({
|
|
||||||
minutes: 30,
|
|
||||||
hour: 0,
|
|
||||||
day: -2,
|
|
||||||
testId: '',
|
|
||||||
sourceCode: '',
|
|
||||||
name: '',
|
|
||||||
nextExecutionTime: undefined,
|
|
||||||
numberOFExecutions: undefined,
|
|
||||||
schedulerId: undefined,
|
|
||||||
environmentId: DEFAULT_ENV_VALUE,
|
|
||||||
device: 'desktop',
|
|
||||||
locations: [],
|
|
||||||
|
|
||||||
advancedOptions: false,
|
|
||||||
headers: [{}],
|
|
||||||
cookies: [{}],
|
|
||||||
basicAuth: {},
|
|
||||||
network: 'wifi',
|
|
||||||
bypassCSP: false,
|
|
||||||
|
|
||||||
slack: false,
|
|
||||||
slackInput: [],
|
|
||||||
webhook: false,
|
|
||||||
webhookInput: [],
|
|
||||||
email: false,
|
|
||||||
emailInput: [],
|
|
||||||
hasNotification: false,
|
|
||||||
options: Map({ message: [], device: 'desktop' }),
|
|
||||||
|
|
||||||
extraCaps: {},
|
|
||||||
|
|
||||||
validateEvery() {
|
|
||||||
if (this.day > -2) return true;
|
|
||||||
return this.minutes >= 5 && this.minutes <= 1440;
|
|
||||||
},
|
|
||||||
validateWebhookEmail() {
|
|
||||||
if (this.channel !== EMAIL) return true;
|
|
||||||
return validateEmail(this.webhookEmail);
|
|
||||||
},
|
|
||||||
validateWebhook() {
|
|
||||||
if (this.channel !== WEBHOOK) return true;
|
|
||||||
return this.webhookId !== '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function fromJS(schedule = {}) {
|
|
||||||
if (schedule instanceof Schedule) return schedule;
|
|
||||||
const options = schedule.options || { message: [] };
|
|
||||||
const extraCaps = options.extraCaps || { };
|
|
||||||
|
|
||||||
let channel = '';
|
|
||||||
if (schedule.webhookEmail) {
|
|
||||||
channel = EMAIL;
|
|
||||||
} else if (schedule.webhookId && schedule.webhook) {
|
|
||||||
channel = schedule.webhook.type === 'slack' ? SLACK : WEBHOOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextExecutionTime = schedule.nextExecutionTime ?
|
|
||||||
DateTime.fromMillis(schedule.nextExecutionTime) : undefined;
|
|
||||||
|
|
||||||
|
|
||||||
let { day, minutes } = schedule;
|
|
||||||
let hour;
|
|
||||||
if (day !== -2) {
|
|
||||||
const utcOffset = new Date().getTimezoneOffset();
|
|
||||||
minutes = minutes - utcOffset
|
|
||||||
minutes = minutes >= 1440 ? (minutes - 1440) : minutes;
|
|
||||||
hour = Math.floor(minutes / 60);
|
|
||||||
}
|
|
||||||
// if (day !== -2) {
|
|
||||||
// const utcOffset = new Date().getTimezoneOffset();
|
|
||||||
// const hourOffset = Math.floor(utcOffset / 60);
|
|
||||||
// const minuteOffset = utcOffset - 60*hourOffset;
|
|
||||||
|
|
||||||
// minutes -= minuteOffset;
|
|
||||||
// hour -= hourOffset;
|
|
||||||
// if (day !== -1) {
|
|
||||||
// const dayOffset = Math.floor(hour/24); // +/-1
|
|
||||||
// day = (day + dayOffset + 7) % 7;
|
|
||||||
// }
|
|
||||||
// hour = (hour + 24) % 24;
|
|
||||||
// }
|
|
||||||
|
|
||||||
const slack = List(options.message).filter(i => i.type === 'slack');
|
|
||||||
const email = List(options.message).filter(i => i.type === 'email');
|
|
||||||
const webhook = List(options.message).filter(i => i.type === 'webhook');
|
|
||||||
|
|
||||||
const headers = extraCaps.headers ? Object.keys(extraCaps.headers).map(k => ({ name: k, value: extraCaps.headers[k] })) : [{}];
|
|
||||||
const cookies = extraCaps.cookies ? Object.keys(extraCaps.cookies).map(k => ({ name: k, value: extraCaps.cookies[k] })) : [{}];
|
|
||||||
|
|
||||||
return new Schedule({
|
|
||||||
...schedule,
|
|
||||||
day,
|
|
||||||
minutes,
|
|
||||||
hour,
|
|
||||||
channel,
|
|
||||||
nextExecutionTime,
|
|
||||||
device: options.device,
|
|
||||||
options,
|
|
||||||
advancedOptions: !!options.extraCaps,
|
|
||||||
bypassCSP: options.bypassCSP,
|
|
||||||
network: options.network,
|
|
||||||
headers,
|
|
||||||
cookies,
|
|
||||||
basicAuth: extraCaps.basicAuth,
|
|
||||||
|
|
||||||
slack: slack.size > 0,
|
|
||||||
slackInput: slack.map(i => parseInt(i.value)).toJS(),
|
|
||||||
|
|
||||||
email: email.size > 0,
|
|
||||||
emailInput: email.map(i => i.value).toJS(),
|
|
||||||
|
|
||||||
webhook: webhook.size > 0,
|
|
||||||
webhookInput: webhook.map(i => parseInt(i.value)).toJS(),
|
|
||||||
|
|
||||||
hasNotification: !!slack || !!email || !!webhook
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getObjetctFromArr(arr) {
|
|
||||||
const obj = {}
|
|
||||||
for (var i = 0; i < arr.length; i++) {
|
|
||||||
const temp = arr[i];
|
|
||||||
obj[temp.name] = temp.value
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
Schedule.prototype.toData = function toData() {
|
|
||||||
const {
|
|
||||||
name, schedulerId, environmentId, device, options, bypassCSP, network, headers, cookies, basicAuth
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
const js = this.toJS();
|
|
||||||
options.device = device;
|
|
||||||
options.bypassCSP = bypassCSP;
|
|
||||||
options.network = network;
|
|
||||||
|
|
||||||
options.extraCaps = {
|
|
||||||
headers: getObjetctFromArr(headers),
|
|
||||||
cookies: getObjetctFromArr(cookies),
|
|
||||||
basicAuth
|
|
||||||
};
|
|
||||||
|
|
||||||
if (js.slack && js.slackInput)
|
|
||||||
options.message = js.slackInput.map(i => ({ type: 'slack', value: i }))
|
|
||||||
if (js.email && js.emailInput)
|
|
||||||
options.message = options.message.concat(js.emailInput.map(i => ({ type: 'email', value: i })))
|
|
||||||
if (js.webhook && js.webhookInput)
|
|
||||||
options.message = options.message.concat(js.webhookInput.map(i => ({ type: 'webhook', value: i })))
|
|
||||||
|
|
||||||
let day = this.day;
|
|
||||||
let hour = undefined;
|
|
||||||
let minutes = this.minutes;
|
|
||||||
if (day !== -2) {
|
|
||||||
const utcOffset = new Date().getTimezoneOffset();
|
|
||||||
minutes = (this.hour * 60) + utcOffset;
|
|
||||||
// minutes += utcOffset;
|
|
||||||
minutes = minutes < 0 ? minutes + 1440 : minutes;
|
|
||||||
}
|
|
||||||
// if (day !== -2) {
|
|
||||||
// const utcOffset = new Date().getTimezoneOffset();
|
|
||||||
// const hourOffset = Math.floor(utcOffset / 60);
|
|
||||||
// const minuteOffset = utcOffset - 60*hourOffset;
|
|
||||||
|
|
||||||
// minutes = minuteOffset;
|
|
||||||
// hour = this.hour + hourOffset;
|
|
||||||
// if (day !== -1) {
|
|
||||||
// const dayOffset = Math.floor(hour/24); // +/-1
|
|
||||||
// day = (day + dayOffset + 7) % 7;
|
|
||||||
// }
|
|
||||||
// hour = (hour + 24) % 24;
|
|
||||||
// }
|
|
||||||
|
|
||||||
delete js.slack;
|
|
||||||
delete js.webhook;
|
|
||||||
delete js.email;
|
|
||||||
delete js.slackInput;
|
|
||||||
delete js.webhookInput;
|
|
||||||
delete js.emailInput;
|
|
||||||
delete js.hasNotification;
|
|
||||||
delete js.headers;
|
|
||||||
delete js.cookies;
|
|
||||||
|
|
||||||
delete js.device;
|
|
||||||
delete js.extraCaps;
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// day, hour, name, minutes, schedulerId, environment,
|
|
||||||
// };
|
|
||||||
return { ...js, day, hour, name, minutes, schedulerId, environmentId, options: options };
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule.prototype.exists = function exists() {
|
|
||||||
return this.schedulerId !== undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule.prototype.valid = function validate() {
|
|
||||||
return this.validateEvery;
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule.prototype.getInterval = function getInterval() {
|
|
||||||
const DAY = List(DAYS).filter(item => item.value === this.day).first();
|
|
||||||
|
|
||||||
if (DAY.value === -2) {
|
|
||||||
return DAY.text + ' ' + this.minutes + ' Minutes'; // Every 30 minutes
|
|
||||||
}
|
|
||||||
|
|
||||||
const HOUR = List(HOURS).filter(item => item.value === this.hour).first();
|
|
||||||
return DAY.text + ' ' + HOUR.text; // Everyday/Sunday 2 AM;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default fromJS;
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
import { Record, List, Set, isImmutable } from 'immutable';
|
|
||||||
import { TYPES as EVENT_TYPES } from 'Types/session/event';
|
|
||||||
|
|
||||||
export const CUSTOM = 'custom';
|
|
||||||
export const CLICK = 'click';
|
|
||||||
export const INPUT = 'input';
|
|
||||||
export const NAVIGATE = 'navigate';
|
|
||||||
export const TEST = 'test';
|
|
||||||
|
|
||||||
export const TYPES = {
|
|
||||||
CLICK,
|
|
||||||
INPUT,
|
|
||||||
CUSTOM,
|
|
||||||
NAVIGATE,
|
|
||||||
TEST,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const Step = defaultValues => class extends Record({
|
|
||||||
key: undefined,
|
|
||||||
name: '',
|
|
||||||
imported: false,
|
|
||||||
isDisabled: false,
|
|
||||||
importTestId: undefined,
|
|
||||||
...defaultValues,
|
|
||||||
}) {
|
|
||||||
hasTarget() {
|
|
||||||
return this.type === CLICK || this.type === INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
isTest() {
|
|
||||||
return this.type === TEST;
|
|
||||||
}
|
|
||||||
|
|
||||||
getEventType() {
|
|
||||||
switch (this.type) {
|
|
||||||
case INPUT:
|
|
||||||
return EVENT_TYPES.INPUT;
|
|
||||||
case CLICK:
|
|
||||||
return EVENT_TYPES.CLICK;
|
|
||||||
case NAVIGATE:
|
|
||||||
return EVENT_TYPES.LOCATION;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validate() {
|
|
||||||
const selectorsOK = this.selectors && this.selectors.size > 0;
|
|
||||||
const valueOK = this.value && this.value.trim().length > 0;
|
|
||||||
switch (this.type) {
|
|
||||||
case INPUT:
|
|
||||||
return selectorsOK;
|
|
||||||
case CLICK:
|
|
||||||
return selectorsOK;
|
|
||||||
case NAVIGATE:
|
|
||||||
return valueOK;
|
|
||||||
case CUSTOM:
|
|
||||||
// if (this.name.length === 0) return false;
|
|
||||||
/* if (window.JSHINT) {
|
|
||||||
window.JSHINT(this.code, { esversion: 6 });
|
|
||||||
const noErrors = window.JSHINT.errors.every(({ code }) => code && code.startsWith('W'));
|
|
||||||
return noErrors;
|
|
||||||
} */
|
|
||||||
return this.code && this.code.length > 0;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toData() {
|
|
||||||
const {
|
|
||||||
value,
|
|
||||||
...step
|
|
||||||
} = this.toJS();
|
|
||||||
delete step.key;
|
|
||||||
return {
|
|
||||||
values: value && [ value ],
|
|
||||||
...step,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Custom = Step({
|
|
||||||
type: CUSTOM,
|
|
||||||
code: '',
|
|
||||||
framework: 'any',
|
|
||||||
template: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const Click = Step({
|
|
||||||
type: CLICK,
|
|
||||||
selectors: List(),
|
|
||||||
customSelector: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const Input = Step({
|
|
||||||
type: INPUT,
|
|
||||||
selectors: List(),
|
|
||||||
value: '',
|
|
||||||
customSelector: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const Navigate = Step({
|
|
||||||
type: NAVIGATE,
|
|
||||||
value: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const TestAsStep = Step({
|
|
||||||
type: TEST,
|
|
||||||
testId: '',
|
|
||||||
name: '',
|
|
||||||
stepsCount: '',
|
|
||||||
steps: List(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const EmptyStep = Step();
|
|
||||||
|
|
||||||
let uniqueKey = 0xff;
|
|
||||||
function nextKey() {
|
|
||||||
uniqueKey += 1;
|
|
||||||
return `${ uniqueKey }`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromJS(initStep = {}) {
|
|
||||||
// TODO: more clear
|
|
||||||
if (initStep.importTestId) return new TestAsStep(initStep).set('steps', List(initStep.steps ? initStep.steps : initStep.test.steps).map(fromJS));
|
|
||||||
// todo: ?
|
|
||||||
if (isImmutable(initStep)) return initStep.set('key', nextKey());
|
|
||||||
|
|
||||||
const values = initStep.values && initStep.values.length > 0 && initStep.values[ 0 ];
|
|
||||||
|
|
||||||
// bad code
|
|
||||||
const step = {
|
|
||||||
...initStep,
|
|
||||||
selectors: Set(initStep.selectors).toList(), // to List not nrcrssary. TODO: check
|
|
||||||
value: initStep.value ? [initStep.value] : values,
|
|
||||||
key: nextKey(),
|
|
||||||
isDisabled: initStep.disabled
|
|
||||||
};
|
|
||||||
// bad code
|
|
||||||
|
|
||||||
if (step.type === CUSTOM) return new Custom(step);
|
|
||||||
if (step.type === CLICK) return new Click(step);
|
|
||||||
if (step.type === INPUT) return new Input(step);
|
|
||||||
if (step.type === NAVIGATE) return new Navigate(step);
|
|
||||||
|
|
||||||
return new EmptyStep();
|
|
||||||
// throw new Error(`Unknown step type: ${step.type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default fromJS;
|
|
||||||
Loading…
Add table
Reference in a new issue