<commit_before>const test = require('ava')
const sinon = require('sinon')
const proxquire = require('proxyquire')
const api = require('../libs/api')
const item = require('./fixtures/item.json')

test('search es error', async (t) => {
  const error = sinon.spy()
  const proxyApi = proxquire('../libs/api', {
    './logger': {
      error
    }
  })
  const errorMessage = 'errorMessage'
  const search = sinon.stub().throws(new Error(errorMessage))
  const backend = { search }
  await proxyApi.search('/stac', undefined, backend, 'endpoint')
  t.is(error.firstCall.args[0].message, errorMessage,
    'Logs Elasticsearch error via Winston transport')
})

test('search /stac', async (t) => {
  const collection = 'collection'
  const results = { results: [{ id: collection }] }
  const search = sinon.stub().resolves(results)
  const backend = { search }
  const actual = await api.search('/stac', undefined, backend, 'endpoint')
  const expectedLinks = [
    {
      rel: 'child',
      href: 'endpoint/collections/collection'
    },
    {
      rel: 'self',
      href: 'endpoint/stac'
    }
  ]
  t.is(search.firstCall.args[1], 'collections')
  t.deepEqual(actual.links, expectedLinks,
    'Returns STAC catalog with links to collections')
})

test('search /stac/search query parameters', async (t) => {
  const search = sinon.stub().resolves({ results: [] })
  const backend = { search }
  const query = { 'test': true }
  const queryParams = {
    page: 1,
    limit: 2,
    query
  }
  api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0], { query },
    'Extracts query to use in search parameters')
  t.is(search.firstCall.args[2], queryParams.page,
    'Extracts page to use as stand alone parameter')
  t.is(search.firstCall.args[3], queryParams.limit,
    'Extracts limit to use as stand alone parameter')
})

test('search /stac/search intersects parameter', async (t) => {
  const search = sinon.stub().resolves({ results: [] })
  const backend = { search }
  const queryParams = {
    intersects: item,
    page: 1,
    limit: 1
  }
  api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0].intersects, item,
    'Uses valid GeoJSON as intersects search parameter')

  search.resetHistory()
  queryParams.intersects = JSON.stringify(item)
  api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0].intersects, item,
    'Handles stringified GeoJSON intersects parameter')
})

test('search /stac/search bbox parameter', async (t) => {
  const search = sinon.stub().resolves({ results: [] })
  const backend = { search }
  const w = -10
  const s = -10
  const e = 10
  const n = 10
  const queryParams = {
    bbox: [w, s, e, n],
    page: 1,
    limit: 1
  }
  const expected = {
    type: 'Feature',
    properties: {},
    geometry: {
      type: 'Polygon',
      coordinates: [[
        [s, w],
        [n, w],
        [n, e],
        [s, e],
        [s, w]
      ]]
    }
  }
  await api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0].intersects, expected,
    'Converts a [w,s,e,n] bbox to an intersects search parameter')
  search.resetHistory()
})

test('search /stac/search time parameter', async (t) => {
  const search = sinon.stub().resolves({ results: [] })
  const backend = { search }
  const range = '2007-03-01T13:00:00Z/2008-05-11T15:30:00Z'
  const queryParams = {
    page: 1,
    limit: 2,
    time: range
  }
  await api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0], { datetime: range },
    'Extracts time query parameter and transforms it into ' +
    'datetime search parameter')
})

test('search /collections', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }
  const search = sinon.stub().resolves({
    meta,
    results: [{
      id: 1,
      links: []
    }]
  })
  const backend = { search }
  const actual = await api.search('/collections', {}, backend, 'endpoint')
  t.is(search.firstCall.args[1], 'collections')
  t.is(actual.collections.length, 1)
  t.is(actual.collections[0].links.length, 4, 'Adds STAC links to each collection')
})

test('search /collections/collectionId', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }
  const search = sinon.stub().resolves({
    meta,
    results: [{
      id: 1,
      links: []
    }]
  })
  const backend = { search }
  const collectionId = 'collectionId'
  let actual = await api.search(
    `/collections/${collectionId}`, { test: 'test' }, backend, 'endpoint'
  )
  t.deepEqual(search.firstCall.args[0], { id: collectionId },
    'Calls search with the collectionId path element as id parameter' +
    ' and ignores other passed filter parameters')
  t.is(actual.links.length, 4, 'Returns the first found collection as object')

  search.reset()
  search.resolves({
    meta,
    results: []
  })
  actual = await api.search(
    `/collections/${collectionId}`, {}, backend, 'endpoint'
  )
  t.is(actual.message, 'Collection not found',
    'Sends error when not collections are found in search')
})

test('search /collections/collectionId/items', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }

  const search = sinon.stub().resolves({
    meta,
    results: []
  })
  const backend = { search }
  const collectionId = 'collectionId'
  await api.search(
    `/collections/${collectionId}/items`, {}, backend, 'endpoint'
  )
  t.deepEqual(search.firstCall.args[0], { collection: collectionId },
    'Calls search with the collectionId path element as collection parameter')
})

test('search /collections/collectionId/items/itemId', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }

  const search = sinon.stub().resolves({
    meta,
    results: [item]
  })
  const backend = { search }
  const itemId = 'itemId'
  const actual = await api.search(
    `/collections/collectionId/items/${itemId}`, {}, backend, 'endpoint'
  )
  t.deepEqual(search.firstCall.args[0], { id: itemId },
    'Calls search with the itemId path element as id parameter' +
    ' and ignores other passed filter parameters')

  t.is(actual.type, 'Feature')
  t.is(actual.links.length, 4, 'Adds STAC links to response object')
})
<commit_msg>Update api search tests for new query logic.<commit_after>const test = require('ava')
const sinon = require('sinon')
const proxquire = require('proxyquire')
const api = require('../libs/api')
const item = require('./fixtures/item.json')

test('search es error', async (t) => {
  const error = sinon.spy()
  const proxyApi = proxquire('../libs/api', {
    './logger': {
      error
    }
  })
  const errorMessage = 'errorMessage'
  const search = sinon.stub().throws(new Error(errorMessage))
  const backend = { search }
  await proxyApi.search('/stac', undefined, backend, 'endpoint')
  t.is(error.firstCall.args[0].message, errorMessage,
    'Logs Elasticsearch error via Winston transport')
})

test('search /stac', async (t) => {
  const collection = 'collection'
  const results = { results: [{ id: collection }] }
  const search = sinon.stub().resolves(results)
  const backend = { search }
  const actual = await api.search('/stac', undefined, backend, 'endpoint')
  const expectedLinks = [
    {
      rel: 'child',
      href: 'endpoint/collections/collection'
    },
    {
      rel: 'self',
      href: 'endpoint/stac'
    }
  ]
  t.is(search.firstCall.args[1], 'collections')
  t.deepEqual(actual.links, expectedLinks,
    'Returns STAC catalog with links to collections')
})

test('search /stac/search query parameters', async (t) => {
  const search = sinon.stub().resolves({ results: [], meta: {} })
  const backend = { search }
  const query = { 'test': true }
  const queryParams = {
    page: 1,
    limit: 2,
    query
  }
  api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0], { query },
    'Extracts query to use in search parameters')
})

test('search /stac/search intersects parameter', async (t) => {
  const search = sinon.stub().resolves({ results: [], meta: {} })
  const backend = { search }
  const queryParams = {
    intersects: item,
    page: 1,
    limit: 1
  }
  api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0].intersects, item,
    'Uses valid GeoJSON as intersects search parameter')

  search.resetHistory()
  queryParams.intersects = JSON.stringify(item)
  api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0].intersects, item,
    'Handles stringified GeoJSON intersects parameter')
})

test('search /stac/search bbox parameter', async (t) => {
  const search = sinon.stub().resolves({ results: [], meta: {} })
  const backend = { search }
  const w = -10
  const s = -10
  const e = 10
  const n = 10
  const queryParams = {
    bbox: [w, s, e, n],
    page: 1,
    limit: 1
  }
  const expected = {
    type: 'Feature',
    properties: {},
    geometry: {
      type: 'Polygon',
      coordinates: [[
        [s, w],
        [n, w],
        [n, e],
        [s, e],
        [s, w]
      ]]
    }
  }
  await api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0].intersects, expected,
    'Converts a [w,s,e,n] bbox to an intersects search parameter')
  search.resetHistory()
})

test('search /stac/search time parameter', async (t) => {
  const search = sinon.stub().resolves({ results: [], meta: {} })
  const backend = { search }
  const range = '2007-03-01T13:00:00Z/2008-05-11T15:30:00Z'
  const queryParams = {
    page: 1,
    limit: 2,
    time: range
  }
  await api.search('/stac/search', queryParams, backend, 'endpoint')
  t.deepEqual(search.firstCall.args[0], { datetime: range },
    'Extracts time query parameter and transforms it into ' +
    'datetime search parameter')
})

test('search /collections', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }
  const search = sinon.stub().resolves({
    meta,
    results: [{
      id: 1,
      links: []
    }]
  })
  const backend = { search }
  const actual = await api.search('/collections', {}, backend, 'endpoint')
  t.is(search.firstCall.args[1], 'collections')
  t.is(actual.collections.length, 1)
  t.is(actual.collections[0].links.length, 4, 'Adds STAC links to each collection')
})

test('search /collections/collectionId', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }
  const search = sinon.stub().resolves({
    meta,
    results: [{
      id: 1,
      links: []
    }]
  })
  const backend = { search }
  const collectionId = 'collectionId'
  let actual = await api.search(
    `/collections/${collectionId}`, { test: 'test' }, backend, 'endpoint'
  )
  t.deepEqual(search.firstCall.args[0], { id: collectionId },
    'Calls search with the collectionId path element as id parameter' +
    ' and ignores other passed filter parameters')
  t.is(actual.links.length, 4, 'Returns the first found collection as object')

  search.reset()
  search.resolves({
    meta,
    results: []
  })
  actual = await api.search(
    `/collections/${collectionId}`, {}, backend, 'endpoint'
  )
  t.is(actual.message, 'Collection not found',
    'Sends error when not collections are found in search')
})

test('search /collections/collectionId/items', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }

  const search = sinon.stub().resolves({
    meta,
    results: []
  })
  const backend = { search }
  const collectionId = 'collectionId'
  await api.search(
    `/collections/${collectionId}/items`, {}, backend, 'endpoint'
  )
  const expectedParameters = {
    query: {
      collection: collectionId
    }
  }
  t.deepEqual(search.firstCall.args[0], expectedParameters,
    'Calls search with the collectionId as part of the query parameter')
})

test('search /collections/collectionId/items/itemId', async (t) => {
  const meta = {
    limit: 1,
    page: 1,
    found: 1,
    returned: 1
  }

  const search = sinon.stub().resolves({
    meta,
    results: [item]
  })
  const backend = { search }
  const itemId = 'itemId'
  const actual = await api.search(
    `/collections/collectionId/items/${itemId}`, {}, backend, 'endpoint'
  )
  t.deepEqual(search.firstCall.args[0], { id: itemId },
    'Calls search with the itemId path element as id parameter' +
    ' and ignores other passed filter parameters')

  t.is(actual.type, 'Feature')
  t.is(actual.links.length, 4, 'Adds STAC links to response object')
})
<|endoftext|>


<commit_before>import _reduce from 'lodash/reduce'
import _isObject from 'lodash/isObject'
import {call} from 'redux-saga/effects'
import {cache} from 'tocco-util'

import {requestSaga} from './rest'

/**
 * Helper to fetch a single entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntity(entityName, key, query, transformer = json => json) {
  const requestQuery = yield call(buildRequestQuery, query)
  const options = {
    method: 'GET',
    queryParams: {
      ...requestQueryToUrlParams(requestQuery),
      _permissions: true,
      _omitLinks: true
    }
  }

  const resp = yield call(requestSaga, `entities/2.0/${entityName}/${key}`, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch the default-display of an entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 */
export function* fetchDisplay(entityName, key) {
  const options = {
    method: 'GET'
  }

  const resp = yield call(requestSaga, `entity/${entityName}/${key}/display`, options)
  return resp.body.display
}

/**
 * Helper to fetch display-expressions of a form for a list of entities
 *
 * @param formName {String} Name of the form
 * @param scope {String} Requested form scope e.g. update or list
 * @param entityKeys {Array} List of entity keys
 * @param displayExpressionFields {Array} List of desired display-expression fields
 */
export function* fetchDisplayExpressions(formName, scope, entityKeys, displayExpressionFields) {
  const options = {
    method: 'GET',
    queryParams: {
      _keys: entityKeys.join(','),
      _paths: displayExpressionFields.join(',')
    }
  }

  const response = yield call(requestSaga, `forms/${formName}_${scope}/display-expressions`, options)

  return response.body.displayExpressions.reduce((acc, val) => ({...acc, [val.key]: val.displayExpressions}), {})
}

/**
 * Helper to fetch the default-display of an entities.
 *
 * @param request {Object} Object containing model and keys of desired entities e.g. {User: ["123"], Gender: ["1", "2"]}
 */
export function* fetchDisplays(request) {
  const options = {
    method: 'POST',
    body: {data: Object.keys(request).map(model => ({model, keys: request[model]}))}
  }
  const response = yield call(requestSaga, 'entities/2.0/displays', options)

  return response.body.data.reduce((acc, value) => (
    {
      ...acc,
      [value.model]: value.values.reduce((acc, value) => ({...acc, [value.key]: value.display}), {})
    }
  ), {})
}

/**
 * Fetch amount of entities
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/count
 */
export function* fetchEntityCount(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {}
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = (endpoint || `entities/2.0/${entityName}`) + '/count'

  const options = {
    method,
    ...(method === 'GET' ? {queryParams: requestQueryToUrlParams(requestQuery)} : {body: requestQuery})
  }

  const response = yield call(requestSaga, resource, options)
  return response.body.count
}

/**
 * Helper to fetch entities.
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/search
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntities(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {},
  transformer = defaultEntityTransformer
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = endpoint || `entities/2.0/${entityName}${method === 'POST' ? '/search' : ''}`

  const options = {
    method,
    queryParams: {
      _omitLinks: true,
      ...(method === 'GET' && requestQueryToUrlParams(requestQuery))
    },
    ...(method === 'POST' && {body: requestQuery})
  }

  const resp = yield call(requestSaga, resource, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch forms.
 * @param formName {String} Name of the requested form
 * @param scope {String} Requested form scope e.g. update or list
 * @param allowNotFound {Boolean} If true and the form does not exist null is returned.
 *                                Otherwise an exception will be thrown.
 */
export function* fetchForm(formName, scope, allowNotFound = false) {
  const request = `${formName}/${scope}`
  const cachedForm = cache.get('form', request)
  if (cachedForm !== undefined) {
    return cachedForm
  }

  const options = {
    ...(allowNotFound && {acceptedStatusCodes: [404]})
  }

  const response = yield call(requestSaga, `forms/${request}`, options)

  if (allowNotFound && response.status === 404) {
    cache.add('form', request, null)
    return null
  }

  const form = yield call(defaultFormTransformer, response.body)
  cache.add('form', request, form)
  return form
}

/**
 * Helper to fetch filters of an entity
 * @param entityName {String} Name of the  entity
 */
export function* fetchSearchFilters(entityName) {
  const response = yield call(requestSaga, `client/searchfilters/${entityName}`)
  return response.body.filters
}

/**
 * Helper to fetch models.
 * @param entityName {String} Name of the entity you like to fetch the model
 */
export function* fetchModel(entityName, transformer = defaultModelTransformer) {
  const cachedModel = cache.get('model', entityName)
  if (cachedModel) {
    return cachedModel
  }

  const resp = yield call(requestSaga, `entities/${entityName}/model`)
  const model = yield call(transformer, resp.body)
  cache.add('model', entityName, model)
  return model
}

export const defaultModelTransformer = json => {
  const model = {
    name: json.name,
    label: json.label,
    paths: {}
  }
  json.fields.forEach(field => {
    model.paths[field.fieldName] = {
      ...field
    }
  })

  json.relations.forEach(relation => {
    model.paths[relation.relationName] = {
      type: 'relation',
      ...relation
    }
  })
  return model
}

export const defaultFormTransformer = json => (json.form)

export const defaultEntityTransformer = json => (json.data)

const isValidSorting = sorting =>
  Array.isArray(sorting) && sorting.length >= 1 && sorting[0].field && sorting[0].order

/**
 * Function that converts a query object into request query object that can be attached to a request.
 * Some options get converted or calculated and other removed if there are undefined.
 *
 * @param options {Object} An object which can contain the following options:
 * - conditions {Object} Object that can contain search fields. Each field
 * - fields {Array} Fields that should be returned
 * - form {String} Name of the form, needed to resolve display expressions and such
 * - limit {Object} Maximum amount of entities to be retrieved
 * - search {Object} Fulltext search on entity
 * - sorting {Array} Array of objects containing a field and order String. e.g. [{field: 'firstname', order: 'asc'}]
 * - page {Number} Current page, needed to calculate offset. Default is undefined which means no offset.
 * - paths {Array} Paths that should be returned
 * - tql {String} TQL query
 * - relations {String} Relations that should be returned
 * - filters {Array} List of filter names to be applied
 * - constriction {String} Id of the constriction that should be applied
 */
export const buildRequestQuery = ({
  conditions,
  fields,
  form,
  limit,
  search,
  sorting,
  page,
  paths,
  tql,
  relations,
  filter,
  keys,
  constriction
} = {}) => (
  {
    ...(conditions ? {conditions} : {}),
    ...(Array.isArray(fields) ? {fields: fields.length === 0 ? '!' : fields} : {}),
    ...(form ? {form} : {}),
    ...(limit ? {limit} : {}),
    ...(search ? {search} : {}),
    ...(isValidSorting(sorting) ? {sort: `${sorting[0].field} ${sorting[0].order}`} : {}),
    ...(page && limit ? {offset: (page - 1) * limit} : {}),
    ...(paths ? {paths} : {}),
    ...(tql ? {where: tql} : {}),
    ...(Array.isArray(relations) ? {relations: relations.length === 0 ? '!' : relations} : {}),
    ...(filter ? {filter} : {}),
    ...(keys ? {keys} : {}),
    ...(constriction ? {constriction} : {})
  }
)

export const requestQueryToUrlParams = queryObject =>
  _reduce(queryObject, (result, value, key) => {
    let add = {}
    if (key === 'conditions') {
      add = flattenObjectValues(value)
    } else {
      add['_' + key] = Array.isArray(value) ? value.join(',') : value
    }

    return {
      ...result,
      ...add
    }
  }, {})

export const flattenObjectValues = value =>
  _reduce(value, (result, value, key) => ({
    ...result,
    [key]: _isObject(value) && value.value ? value.value : value
  }), {})
<commit_msg>refactor(app-extensions): allow multi sorting in helper<commit_after>import _reduce from 'lodash/reduce'
import _isObject from 'lodash/isObject'
import {call} from 'redux-saga/effects'
import {cache} from 'tocco-util'

import {requestSaga} from './rest'

/**
 * Helper to fetch a single entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntity(entityName, key, query, transformer = json => json) {
  const requestQuery = yield call(buildRequestQuery, query)
  const options = {
    method: 'GET',
    queryParams: {
      ...requestQueryToUrlParams(requestQuery),
      _permissions: true,
      _omitLinks: true
    }
  }

  const resp = yield call(requestSaga, `entities/2.0/${entityName}/${key}`, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch the default-display of an entity
 *
 * @param entityName {String} Name of the entity
 * @param key {String} key of the entity
 */
export function* fetchDisplay(entityName, key) {
  const options = {
    method: 'GET'
  }

  const resp = yield call(requestSaga, `entity/${entityName}/${key}/display`, options)
  return resp.body.display
}

/**
 * Helper to fetch display-expressions of a form for a list of entities
 *
 * @param formName {String} Name of the form
 * @param scope {String} Requested form scope e.g. update or list
 * @param entityKeys {Array} List of entity keys
 * @param displayExpressionFields {Array} List of desired display-expression fields
 */
export function* fetchDisplayExpressions(formName, scope, entityKeys, displayExpressionFields) {
  const options = {
    method: 'GET',
    queryParams: {
      _keys: entityKeys.join(','),
      _paths: displayExpressionFields.join(',')
    }
  }

  const response = yield call(requestSaga, `forms/${formName}_${scope}/display-expressions`, options)

  return response.body.displayExpressions.reduce((acc, val) => ({...acc, [val.key]: val.displayExpressions}), {})
}

/**
 * Helper to fetch the default-display of an entities.
 *
 * @param request {Object} Object containing model and keys of desired entities e.g. {User: ["123"], Gender: ["1", "2"]}
 */
export function* fetchDisplays(request) {
  const options = {
    method: 'POST',
    body: {data: Object.keys(request).map(model => ({model, keys: request[model]}))}
  }
  const response = yield call(requestSaga, 'entities/2.0/displays', options)

  return response.body.data.reduce((acc, value) => (
    {
      ...acc,
      [value.model]: value.values.reduce((acc, value) => ({...acc, [value.key]: value.display}), {})
    }
  ), {})
}

/**
 * Fetch amount of entities
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/count
 */
export function* fetchEntityCount(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {}
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = (endpoint || `entities/2.0/${entityName}`) + '/count'

  const options = {
    method,
    ...(method === 'GET' ? {queryParams: requestQueryToUrlParams(requestQuery)} : {body: requestQuery})
  }

  const response = yield call(requestSaga, resource, options)
  return response.body.count
}

/**
 * Helper to fetch entities.
 *
 * @param entityName {String} Name of the entity
 * @param query {Object} see 'buildRequestQuery' function
 * @param requestOptions {Object} An object which can contain the following options:
 * - method {String} HTTP Method of request. Default is POST
 * - endpoint {String} To overwrite default endpoint entities/2.0/{entityName}/search
 * @param transformer {function} Function to directly manipulate the result. By default returns data attribute
 */
export function* fetchEntities(
  entityName,
  query,
  {
    method = 'POST',
    endpoint
  } = {},
  transformer = defaultEntityTransformer
) {
  const requestQuery = yield call(buildRequestQuery, query)
  const resource = endpoint || `entities/2.0/${entityName}${method === 'POST' ? '/search' : ''}`

  const options = {
    method,
    queryParams: {
      _omitLinks: true,
      ...(method === 'GET' && requestQueryToUrlParams(requestQuery))
    },
    ...(method === 'POST' && {body: requestQuery})
  }

  const resp = yield call(requestSaga, resource, options)
  return yield call(transformer, resp.body)
}

/**
 * Helper to fetch forms.
 * @param formName {String} Name of the requested form
 * @param scope {String} Requested form scope e.g. update or list
 * @param allowNotFound {Boolean} If true and the form does not exist null is returned.
 *                                Otherwise an exception will be thrown.
 */
export function* fetchForm(formName, scope, allowNotFound = false) {
  const request = `${formName}/${scope}`
  const cachedForm = cache.get('form', request)
  if (cachedForm !== undefined) {
    return cachedForm
  }

  const options = {
    ...(allowNotFound && {acceptedStatusCodes: [404]})
  }

  const response = yield call(requestSaga, `forms/${request}`, options)

  if (allowNotFound && response.status === 404) {
    cache.add('form', request, null)
    return null
  }

  const form = yield call(defaultFormTransformer, response.body)
  cache.add('form', request, form)
  return form
}

/**
 * Helper to fetch filters of an entity
 * @param entityName {String} Name of the  entity
 */
export function* fetchSearchFilters(entityName) {
  const response = yield call(requestSaga, `client/searchfilters/${entityName}`)
  return response.body.filters
}

/**
 * Helper to fetch models.
 * @param entityName {String} Name of the entity you like to fetch the model
 */
export function* fetchModel(entityName, transformer = defaultModelTransformer) {
  const cachedModel = cache.get('model', entityName)
  if (cachedModel) {
    return cachedModel
  }

  const resp = yield call(requestSaga, `entities/${entityName}/model`)
  const model = yield call(transformer, resp.body)
  cache.add('model', entityName, model)
  return model
}

export const defaultModelTransformer = json => {
  const model = {
    name: json.name,
    label: json.label,
    paths: {}
  }
  json.fields.forEach(field => {
    model.paths[field.fieldName] = {
      ...field
    }
  })

  json.relations.forEach(relation => {
    model.paths[relation.relationName] = {
      type: 'relation',
      ...relation
    }
  })
  return model
}

export const defaultFormTransformer = json => (json.form)

export const defaultEntityTransformer = json => (json.data)

/**
 * Function that converts a query object into request query object that can be attached to a request.
 * Some options get converted or calculated and other removed if there are undefined.
 *
 * @param options {Object} An object which can contain the following options:
 * - conditions {Object} Object that can contain search fields. Each field
 * - fields {Array} Fields that should be returned
 * - form {String} Name of the form, needed to resolve display expressions and such
 * - limit {Object} Maximum amount of entities to be retrieved
 * - search {Object} Fulltext search on entity
 * - sorting {Array} Array of objects containing a field and order String. e.g. [{field: 'firstname', order: 'asc'}]
 * - page {Number} Current page, needed to calculate offset. Default is undefined which means no offset.
 * - paths {Array} Paths that should be returned
 * - tql {String} TQL query
 * - relations {String} Relations that should be returned
 * - filters {Array} List of filter names to be applied
 * - constriction {String} Id of the constriction that should be applied
 */
export const buildRequestQuery = ({
  conditions,
  fields,
  form,
  limit,
  search,
  sorting,
  page,
  paths,
  tql,
  relations,
  filter,
  keys,
  constriction
} = {}) => (
  {
    ...(conditions ? {conditions} : {}),
    ...(Array.isArray(fields) ? {fields: fields.length === 0 ? '!' : fields} : {}),
    ...(form ? {form} : {}),
    ...(limit ? {limit} : {}),
    ...(search ? {search} : {}),
    ...(sorting ? {sort: sorting.map(s => `${s.field} ${s.order}`).join(', ')} : {}),
    ...(page && limit ? {offset: (page - 1) * limit} : {}),
    ...(paths ? {paths} : {}),
    ...(tql ? {where: tql} : {}),
    ...(Array.isArray(relations) ? {relations: relations.length === 0 ? '!' : relations} : {}),
    ...(filter ? {filter} : {}),
    ...(keys ? {keys} : {}),
    ...(constriction ? {constriction} : {})
  }
)

export const requestQueryToUrlParams = queryObject =>
  _reduce(queryObject, (result, value, key) => {
    let add = {}
    if (key === 'conditions') {
      add = flattenObjectValues(value)
    } else {
      add['_' + key] = Array.isArray(value) ? value.join(',') : value
    }

    return {
      ...result,
      ...add
    }
  }, {})

export const flattenObjectValues = value =>
  _reduce(value, (result, value, key) => ({
    ...result,
    [key]: _isObject(value) && value.value ? value.value : value
  }), {})
<|endoftext|>


<commit_before>import traverse from "../lib";
import assert from "assert";
import { parse } from "babylon";
import * as t from "babel-types";

describe("path/replacement", function () {
  describe("replaceWith", function () {
    const ast = parse("export default function() {};", { sourceType: "module" });

    it("replaces declaration in ExportDefaultDeclaration node", function() {
      traverse(ast, {
        FunctionDeclaration(path) {
          path.replaceWith(t.arrayExpression([
            t.functionExpression(
              path.node.id,
              path.node.params,
              path.node.body,
              path.node.generator,
              path.node.async
            ),
          ]));
        },
      });

      assert(ast.program.body[0].declaration.type == "ArrayExpression");
    });
  });
});
<commit_msg>Added individual test cases for possible errors with path.replaceWith (#5779)<commit_after>import traverse from "../lib";
import assert from "assert";
import { parse } from "babylon";
import * as t from "babel-types";
import { expect } from "chai";

describe("path/replacement", function () {
  describe("replaceWith", function () {
    it("replaces declaration in ExportDefaultDeclaration node", function() {
      const ast = parse("export default function() {};", { sourceType: "module" });
      traverse(ast, {
        FunctionDeclaration(path) {
          path.replaceWith(t.arrayExpression([
            t.functionExpression(
              path.node.id,
              path.node.params,
              path.node.body,
              path.node.generator,
              path.node.async
            ),
          ]));
        },
      });

      assert(ast.program.body[0].declaration.type == "ArrayExpression");
    });

    it("throws error when trying to replace Program with a non-Program node", function() {
      const ast = parse("var x = 3;");
      expect(function() {
        traverse(ast, {
          Program(path) {
            path.replaceWith(t.identifier("a"));
          },
        });
      }).to.throw(/You can only replace a Program root node with another Program node/);
    });

    it("throws error when used with an array of nodes", function() {
      const ast = parse("function abc() {}; var test = 17;");
      expect(function() {
        traverse(ast, {
          NumericLiteral(path) {
            path.replaceWith([
              t.identifier("should"),
              t.identifier("never"),
              t.identifier("happen"),
            ]);
          },
        });
      }).to.throw(
        /Don't use `path\.replaceWith\(\)` with an array of nodes, use `path\.replaceWithMultiple\(\)`/
      );
    });

    it("throws error when used with source string", function() {
      const ast = parse("(function() { var x = 3; var y = 17; var c = x + y; })();");
      expect(function() {
        traverse(ast, {
          BinaryExpression(path) {
            path.replaceWith("17 + 23");
          },
        });
      }).to.throw(
        /Don't use `path\.replaceWith\(\)` with a source string, use `path\.replaceWithSourceString\(\)`/
      );
    });

    it("throws error when trying to replace removed node", function() {
      const ast = parse("var z = 'abc';");
      expect(function() {
        traverse(ast, {
          StringLiteral(path) {
            path.remove();
            path.replaceWith(t.identifier("p"));
          },
        });
      }).to.throw(
        /You can't replace this node, we've already removed it/,
      );
    });

    it("throws error when passed a falsy value", function() {
      const ast = parse("var z = 'abc';");
      expect(function() {
        traverse(ast, {
          StringLiteral(path) {
            path.replaceWith();
          },
        });
      }).to.throw(
        /You passed `path\.replaceWith\(\)` a falsy node, use `path\.remove\(\)` instead/,
      );
    });

  });
});
<|endoftext|>


<commit_before>const ip = require('ip');
const webpack = require('webpack');
const getPort = require('get-port');
const { resolve } = require('path');
const clear = require('console-clear');
const { writeFile } = require('fs.promised');
const { bold, red, green } = require('chalk');
const DevServer = require('webpack-dev-server');
const clientConfig = require('./webpack-client-config');
const serverConfig = require('./webpack-server-config');
const transformConfig = require('./transform-config');
const { error, isDir, warn } = require('../../util');

async function devBuild(env) {
	let config = clientConfig(env);

	await transformConfig(env, config);

	let userPort = parseInt(process.env.PORT || config.devServer.port, 10) || 8080;
	let port = await getPort(userPort);

	let compiler = webpack(config);
	return new Promise((res, rej) => {
		compiler.plugin('emit', (compilation, callback) => {
			var missingDeps = compilation.missingDependencies;
			var nodeModulesPath = resolve(__dirname, '../../../node_modules');

			// ...tell webpack to watch node_modules recursively until they appear.
			if (missingDeps.some(file => file.indexOf(nodeModulesPath) !== -1)) {
				compilation.contextDependencies.push(nodeModulesPath);
			}

			callback();
		});

		compiler.plugin('done', stats => {
			let devServer = config.devServer;
			let protocol = (process.env.HTTPS || devServer.https) ? 'https' : 'http';

			let host = process.env.HOST || devServer.host || 'localhost';
			if (host === '0.0.0.0') host = 'localhost';

			let serverAddr = `${protocol}://${host}:${bold(port)}`;
			let localIpAddr = `${protocol}://${ip.address()}:${bold(port)}`;

			clear();

			if (stats.hasErrors()) {
				process.stdout.write(red('\Build failed!\n\n'));
			} else {
				process.stdout.write(green('Compiled successfully!\n\n'));

				if (userPort !== port) {
					process.stdout.write(`Port ${bold(userPort)} is in use, using ${bold(port)} instead\n\n`);
				}
				process.stdout.write('You can view the application in browser.\n\n');
				process.stdout.write(`${bold('Local:')}            ${serverAddr}\n`);
				process.stdout.write(`${bold('On Your Network:')}  ${localIpAddr}\n`);
			}

			showStats(stats);
		});

		compiler.plugin('failed', rej);

		let c = Object.assign({}, config.devServer, {
			stats: { colors:true }
		});

		let server = new DevServer(compiler, c);
		server.listen(port);
		res(server);
	});
}

async function prodBuild(env) {
	let config = clientConfig(env);
	await transformConfig(env, config);

	if (env.prerender) {
		let ssrConfig = serverConfig(env);
		await transformConfig(env, ssrConfig, true);
		let serverCompiler = webpack(ssrConfig);
		await runCompiler(serverCompiler);
	}

	let clientCompiler = webpack(config);
	let stats = await runCompiler(clientCompiler);

	// Timeout for plugins that work on `after-emit` event of webpack
	await new Promise(r => setTimeout(r, 20));

	return showStats(stats);
}

function runCompiler(compiler) {
	return new Promise((res, rej) => {
		compiler.run((err, stats) => {
			if (stats && stats.hasErrors()) {
				showStats(stats);
			}

			if (err || (stats && stats.hasErrors())) {
				rej(red('Build failed! ' + err));
			}

			res(stats);
		});
	});
}

function showStats(stats) {
	let info = stats.toJson('errors-only');

	if (stats.hasErrors()) {
		info.errors.map(stripLoaderPrefix).forEach(msg => error(msg));
	}

	if (stats.hasWarnings()) {
		info.warnings.map(stripLoaderPrefix).forEach(msg => warn(msg));
	}

	return stats;
}

function writeJsonStats(stats) {
	let outputPath = resolve(process.cwd(), 'stats.json');
	let jsonStats = stats.toJson({ json:true, chunkModules:true, source:false });

	function strip(stats) {
		stats.modules.forEach(stripLoaderFromModuleNames);
		stats.chunks.forEach(c => {
			(c.modules || (c.mapModules!=null ? c.mapModules(Object) : c.getModules())).forEach(stripLoaderFromModuleNames);
		});
		if (stats.children) stats.children.forEach(strip);
	}

	strip(jsonStats);

	return writeFile(outputPath, JSON.stringify(jsonStats)).then(() => {
		process.stdout.write('\nWebpack output stats generated.\n\n');
		process.stdout.write('You can upload your stats.json to:\n');
		process.stdout.write('- https://chrisbateman.github.io/webpack-visualizer/\n');
		process.stdout.write('- https://webpack.github.io/analyse/\n');
	});
}

const keysToNormalize = [
	'issuer',
	'issuerName',
	'identifier',
	'name',
	'module',
	'moduleName',
	'moduleIdentifier'
];

/** Removes all loaders from any resource identifiers found in a string */
function stripLoaderPrefix(str) {
	if (typeof str==='string') {
		return str.replace(/(^|\b|@)(\.\/~|\.{0,2}\/[^\s]+\/node_modules)\/\w+-loader(\/[^?!]+)?(\?\?[\w_.-]+|\?({[\s\S]*?})?)?!/g, '');
	}
	return str;
}

function stripLoaderFromModuleNames(m) {
	for (let key in m) {
		if (m.hasOwnProperty(key) && m[key]!=null && ~keysToNormalize.indexOf(key)) {
			m[key] = stripLoaderPrefix(m[key]);
		}
	}

	if (m.reasons) {
		m.reasons.forEach(stripLoaderFromModuleNames);
	}

	return m;
}

module.exports = function (env, watch=false) {
	env.isProd = env.production; // shorthand
	env.cwd = resolve(env.cwd || process.cwd());

	// env.src='src' via `build` default
	let src = resolve(env.cwd, env.src);
	env.src = isDir(src) ? src : env.cwd;

	// attach sourcing helper
	env.source = dir => resolve(env.src, dir);

	// determine build-type to run
	return (watch ? devBuild : prodBuild)(env);
};

module.exports.writeJsonStats = writeJsonStats;
<commit_msg>satisfy linter<commit_after>const ip = require('ip');
const webpack = require('webpack');
const getPort = require('get-port');
const { resolve } = require('path');
const clear = require('console-clear');
const { writeFile } = require('fs.promised');
const { bold, red, green } = require('chalk');
const DevServer = require('webpack-dev-server');
const clientConfig = require('./webpack-client-config');
const serverConfig = require('./webpack-server-config');
const transformConfig = require('./transform-config');
const { error, isDir, warn } = require('../../util');

async function devBuild(env) {
	let config = clientConfig(env);

	await transformConfig(env, config);

	let userPort = parseInt(process.env.PORT || config.devServer.port, 10) || 8080;
	let port = await getPort(userPort);

	let compiler = webpack(config);
	return new Promise((res, rej) => {
		compiler.plugin('emit', (compilation, callback) => {
			var missingDeps = compilation.missingDependencies;
			var nodeModulesPath = resolve(__dirname, '../../../node_modules');

			// ...tell webpack to watch node_modules recursively until they appear.
			if (missingDeps.some(file => file.indexOf(nodeModulesPath) !== -1)) {
				compilation.contextDependencies.push(nodeModulesPath);
			}

			callback();
		});

		compiler.plugin('done', stats => {
			let devServer = config.devServer;
			let protocol = (process.env.HTTPS || devServer.https) ? 'https' : 'http';

			let host = process.env.HOST || devServer.host || 'localhost';
			if (host === '0.0.0.0') host = 'localhost';

			let serverAddr = `${protocol}://${host}:${bold(port)}`;
			let localIpAddr = `${protocol}://${ip.address()}:${bold(port)}`;

			clear();

			if (stats.hasErrors()) {
				process.stdout.write(red('Build failed!\n\n'));
			} else {
				process.stdout.write(green('Compiled successfully!\n\n'));

				if (userPort !== port) {
					process.stdout.write(`Port ${bold(userPort)} is in use, using ${bold(port)} instead\n\n`);
				}
				process.stdout.write('You can view the application in browser.\n\n');
				process.stdout.write(`${bold('Local:')}            ${serverAddr}\n`);
				process.stdout.write(`${bold('On Your Network:')}  ${localIpAddr}\n`);
			}

			showStats(stats);
		});

		compiler.plugin('failed', rej);

		let c = Object.assign({}, config.devServer, {
			stats: { colors:true }
		});

		let server = new DevServer(compiler, c);
		server.listen(port);
		res(server);
	});
}

async function prodBuild(env) {
	let config = clientConfig(env);
	await transformConfig(env, config);

	if (env.prerender) {
		let ssrConfig = serverConfig(env);
		await transformConfig(env, ssrConfig, true);
		let serverCompiler = webpack(ssrConfig);
		await runCompiler(serverCompiler);
	}

	let clientCompiler = webpack(config);
	let stats = await runCompiler(clientCompiler);

	// Timeout for plugins that work on `after-emit` event of webpack
	await new Promise(r => setTimeout(r, 20));

	return showStats(stats);
}

function runCompiler(compiler) {
	return new Promise((res, rej) => {
		compiler.run((err, stats) => {
			if (stats && stats.hasErrors()) {
				showStats(stats);
			}

			if (err || (stats && stats.hasErrors())) {
				rej(red('Build failed! ' + err));
			}

			res(stats);
		});
	});
}

function showStats(stats) {
	let info = stats.toJson('errors-only');

	if (stats.hasErrors()) {
		info.errors.map(stripLoaderPrefix).forEach(msg => error(msg));
	}

	if (stats.hasWarnings()) {
		info.warnings.map(stripLoaderPrefix).forEach(msg => warn(msg));
	}

	return stats;
}

function writeJsonStats(stats) {
	let outputPath = resolve(process.cwd(), 'stats.json');
	let jsonStats = stats.toJson({ json:true, chunkModules:true, source:false });

	function strip(stats) {
		stats.modules.forEach(stripLoaderFromModuleNames);
		stats.chunks.forEach(c => {
			(c.modules || (c.mapModules!=null ? c.mapModules(Object) : c.getModules())).forEach(stripLoaderFromModuleNames);
		});
		if (stats.children) stats.children.forEach(strip);
	}

	strip(jsonStats);

	return writeFile(outputPath, JSON.stringify(jsonStats)).then(() => {
		process.stdout.write('\nWebpack output stats generated.\n\n');
		process.stdout.write('You can upload your stats.json to:\n');
		process.stdout.write('- https://chrisbateman.github.io/webpack-visualizer/\n');
		process.stdout.write('- https://webpack.github.io/analyse/\n');
	});
}

const keysToNormalize = [
	'issuer',
	'issuerName',
	'identifier',
	'name',
	'module',
	'moduleName',
	'moduleIdentifier'
];

/** Removes all loaders from any resource identifiers found in a string */
function stripLoaderPrefix(str) {
	if (typeof str==='string') {
		return str.replace(/(^|\b|@)(\.\/~|\.{0,2}\/[^\s]+\/node_modules)\/\w+-loader(\/[^?!]+)?(\?\?[\w_.-]+|\?({[\s\S]*?})?)?!/g, '');
	}
	return str;
}

function stripLoaderFromModuleNames(m) {
	for (let key in m) {
		if (m.hasOwnProperty(key) && m[key]!=null && ~keysToNormalize.indexOf(key)) {
			m[key] = stripLoaderPrefix(m[key]);
		}
	}

	if (m.reasons) {
		m.reasons.forEach(stripLoaderFromModuleNames);
	}

	return m;
}

module.exports = function (env, watch=false) {
	env.isProd = env.production; // shorthand
	env.cwd = resolve(env.cwd || process.cwd());

	// env.src='src' via `build` default
	let src = resolve(env.cwd, env.src);
	env.src = isDir(src) ? src : env.cwd;

	// attach sourcing helper
	env.source = dir => resolve(env.src, dir);

	// determine build-type to run
	return (watch ? devBuild : prodBuild)(env);
};

module.exports.writeJsonStats = writeJsonStats;
<|endoftext|>


<commit_before>const E2eHelpers = require('../e2e/e2e-helpers');
const Timeouts = require('../e2e/timeouts.js');
const DisabilityHelpers = require('../e2e/disability-helpers');
const LoginHelpers = require('../e2e/login-helpers');

module.exports = E2eHelpers.createE2eTest(
  (client) => {
    const token = LoginHelpers.getUserToken();

    DisabilityHelpers.initClaimsListMock(token);
    DisabilityHelpers.initClaimDetailMocks(token, false, false, false, 3);

    LoginHelpers.logIn(token, client, '/disability-benefits/track-claims', 3);

    // Claim list page
    client
      .url(`${E2eHelpers.baseUrl}/disability-benefits/track-claims`);

    E2eHelpers.overrideSmoothScrolling(client);

    // Click consolidated claims button
    client
      .waitForElementVisible('a.claim-list-item', Timeouts.slow)
      .axeCheck('.main');

    client
      .click('a.claims-combined')
      .waitForElementVisible('.claims-status-upload-header', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-modal-inner button.usa-button');

    // Claim status tab
    client
      .click('a.claim-list-item:first-child')
      .waitForElementVisible('.claim-title', Timeouts.normal)
      .axeCheck('.main');

    // claim estimation page
    client
      // have to scroll to trigger all phases to show up
      .execute('window.scrollTo(0,8000)')
      .pause(500)
      .waitForElementPresent('.claim-completion-estimation', Timeouts.normal)
      .click('.claim-completion-estimation a')
      .waitForElementVisible('.estimation-header', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal);

    // files tab
    client
      .click('.va-tabs li:nth-child(2) > a')
      .waitForElementVisible('.file-request-list-item', Timeouts.normal)
      .axeCheck('.main');

    // Ask VA page
    client
      .click('.usa-alert-info a')
      .waitForElementVisible('.request-decision-button', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal)
      .click('.va-tabs li:nth-child(2) > a')
      .waitForElementVisible('.file-request-list-item', Timeouts.normal);

    // document request page
    client
      .click('.file-request-list-item a')
      .waitForElementVisible('.tracked-item-due', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal);

    // turn in evidence page
    client
      .click('.submit-additional-evidence a')
      .waitForElementVisible('.upload-files', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal);

    // details tab
    client
      .click('.va-tabs li:nth-child(3) > a')
      .waitForElementVisible('.claim-types', Timeouts.normal)
      .axeCheck('.main');

    client.end();
  }
);
<commit_msg>Updated selector used in Disability Benefits tests.<commit_after>const E2eHelpers = require('../e2e/e2e-helpers');
const Timeouts = require('../e2e/timeouts.js');
const DisabilityHelpers = require('../e2e/disability-helpers');
const LoginHelpers = require('../e2e/login-helpers');

module.exports = E2eHelpers.createE2eTest(
  (client) => {
    const token = LoginHelpers.getUserToken();

    DisabilityHelpers.initClaimsListMock(token);
    DisabilityHelpers.initClaimDetailMocks(token, false, false, false, 3);

    LoginHelpers.logIn(token, client, '/disability-benefits/track-claims', 3);

    // Claim list page
    client
      .url(`${E2eHelpers.baseUrl}/disability-benefits/track-claims`);

    E2eHelpers.overrideSmoothScrolling(client);

    // Click consolidated claims button
    client
      .waitForElementVisible('a.claim-list-item', Timeouts.slow)
      .axeCheck('.main');

    client
      .click('a.claims-combined')
      .waitForElementVisible('.claims-status-upload-header', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-modal-inner button.usa-button');

    // Claim status tab
    client
      .click('a.claim-list-item:first-child')
      .waitForElementVisible('.claim-title', Timeouts.normal)
      .axeCheck('.main');

    // claim estimation page
    client
      // have to scroll to trigger all phases to show up
      .execute('window.scrollTo(0,8000)')
      .pause(500)
      .waitForElementPresent('.claim-completion-estimation', Timeouts.normal)
      .click('.claim-completion-estimation a')
      .waitForElementVisible('.estimation-header', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list:not(.va-nav-breadcrumbs--gate) li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal);

    // files tab
    client
      .click('.va-tabs li:nth-child(2) > a')
      .waitForElementVisible('.file-request-list-item', Timeouts.normal)
      .axeCheck('.main');

    // Ask VA page
    client
      .click('.usa-alert-info a')
      .waitForElementVisible('.request-decision-button', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list:not(.va-nav-breadcrumbs--gate) li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal)
      .click('.va-tabs li:nth-child(2) > a')
      .waitForElementVisible('.file-request-list-item', Timeouts.normal);

    // document request page
    client
      .click('.file-request-list-item a')
      .waitForElementVisible('.tracked-item-due', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list:not(.va-nav-breadcrumbs--gate) li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal);

    // turn in evidence page
    client
      .click('.submit-additional-evidence a')
      .waitForElementVisible('.upload-files', Timeouts.normal)
      .axeCheck('.main');

    client
      .click('.va-nav-breadcrumbs-list:not(.va-nav-breadcrumbs--gate) li:nth-child(2) a')
      .waitForElementVisible('.claim-title', Timeouts.normal);

    // details tab
    client
      .click('.va-tabs li:nth-child(3) > a')
      .waitForElementVisible('.claim-types', Timeouts.normal)
      .axeCheck('.main');

    client.end();
  }
);
<|endoftext|>


<commit_before>import util from 'util';

import { parseHTML } from '../test_helpers';
import { mount,
         createLocalVue } from '@vue/test-utils';

import Vuex from 'vuex';
import annotations from "store/modules/annotations";
import annotations_ui from "store/modules/annotations_ui";
import footnotes_ui from "store/modules/footnotes_ui";
import resources_ui from "store/modules/resources_ui";

import ResourceSection from 'components/ResourceSection';

const localVue = createLocalVue();
localVue.use(Vuex);

const DEFAULT_ANNOTATION = Object.freeze({
  "id": 1,
  "resource_id": 1,
  "start_paragraph": 0,
  "end_paragraph": Number.MAX_SAFE_INTEGER,
  "start_offset": 0,
  "end_offset": Number.MAX_SAFE_INTEGER,
  "kind": "highlight",
  "content": null
});

describe('ResourceSection', () => {
  let store;

  beforeEach(() => {
    store = new Vuex.Store({
      modules: {annotations,
                annotations_ui,
                footnotes_ui,
                resources_ui}
    });

    // Reset the store because right now cloneDeep isn't working
    store.state.annotations.all.map(a => store.commit('annotations/destroy', a));
  });

  test.each([
    ['wraps text in an annotation when the annotation entirely spans the text',
     '
%s
', ['foo bar'],
     [DEFAULT_ANNOTATION]],

    ['wraps inline elements in an annotation when the annotation entirely spans the elements',
     '
%s
', ['foo bar'],
     [DEFAULT_ANNOTATION]],

    ['wraps innerHTML of a block level element rather than wrapping the block element itself',
     '

%s

', ['foo bar'],
     [DEFAULT_ANNOTATION]],

    ['splits text when an annotation starts midway through the text',
     '
f%s
', ['oo bar'],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, start_offset: 1}]],

    ['splits text when an annotation ends midway through the text',
     '
%soo bar
', ['f'],
     [{...DEFAULT_ANNOTATION, end_paragraph: 1, end_offset: 1}]],

    ['splits text when an annotation begins and ends midway through the text',
     '
f%sr
', ['oo ba'],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, end_paragraph: 1, start_offset: 1, end_offset: 6}]],

    ['splits an annotation into chunks when beginning within an element and ending outside of it',
     '
f%s%sr
', ['oo', 'ba'],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, end_paragraph: 1, start_offset: 1, end_offset: 5}]],

  ])('%s', (testTitle, sectionHTML, toSelect, annotations) => {
    store.commit('annotations/append', annotations);
    const wrapper = mount(ResourceSection, {store, localVue, propsData: {
      index: 1,
      el: parseHTML(util.format(sectionHTML, ...toSelect))
    }});
    expect(wrapper.findAll(`.selected-text`).wrappers.map(w => parseHTML(w.html()).innerHTML)).toEqual(toSelect);
  });
});
<commit_msg>Add additional tests<commit_after>import util from 'util';

import { parseHTML } from '../test_helpers';
import { mount,
         createLocalVue } from '@vue/test-utils';

import Vuex from 'vuex';
import annotations from "store/modules/annotations";
import annotations_ui from "store/modules/annotations_ui";
import footnotes_ui from "store/modules/footnotes_ui";
import resources_ui from "store/modules/resources_ui";

import ResourceSection from 'components/ResourceSection';

const localVue = createLocalVue();
localVue.use(Vuex);

const DEFAULT_ANNOTATION = Object.freeze({
  "id": 1,
  "resource_id": 1,
  "start_paragraph": 0,
  "end_paragraph": Number.MAX_SAFE_INTEGER,
  "start_offset": 0,
  "end_offset": Number.MAX_SAFE_INTEGER,
  "kind": "highlight",
  "content": null
});

describe('ResourceSection', () => {
  let store;

  beforeEach(() => {
    store = new Vuex.Store({
      modules: {annotations,
                annotations_ui,
                footnotes_ui,
                resources_ui}
    });

    // Reset the store because right now cloneDeep isn't working
    store.state.annotations.all.map(a => store.commit('annotations/destroy', a));
  });

  test.each([
    ['wraps text in an annotation when the annotation entirely spans the text',
     '
%s
', ['foo bar'],
     [DEFAULT_ANNOTATION]],

    ['wraps inline elements in an annotation when the annotation entirely spans the elements',
     '
%s
', ['foo bar'],
     [DEFAULT_ANNOTATION]],

    ['wraps innerHTML of a block level element rather than wrapping the block element itself',
     '

%s

', ['foo bar'],
     [DEFAULT_ANNOTATION]],

    ['splits text when an annotation starts midway through the text',
     '
f%s
', ['oo bar'],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, start_offset: 1}]],

    ['splits text when an annotation ends midway through the text',
     '
%soo bar
', ['f'],
     [{...DEFAULT_ANNOTATION, end_paragraph: 1, end_offset: 1}]],

    ['splits text when an annotation begins and ends midway through the text',
     '
f%sr
', ['oo ba'],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, end_paragraph: 1, start_offset: 1, end_offset: 6}]],

    ['splits an annotation into chunks when beginning within an element and ending outside of it',
     '
f%s%sr
', ['oo', 'ba'],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, end_paragraph: 1, start_offset: 1, end_offset: 5}]],

    ['preserves whitespace at beginning of annotated text',
     '
%s
', [' foo'],
     [DEFAULT_ANNOTATION]],

    ['preserves whitespace at end of annotated text',
     '
%s
', ['foo '],
     [DEFAULT_ANNOTATION]]
  ])('%s', (testTitle, sectionHTML, toSelect, annotations) => {
    store.commit('annotations/append', annotations);
    const wrapper = mount(ResourceSection, {store, localVue, propsData: {
      index: 1,
      el: parseHTML(util.format(sectionHTML, ...toSelect))
    }});
    expect(wrapper.findAll(`.selected-text`).wrappers.map(w => parseHTML(w.html()).innerHTML)).toEqual(toSelect);
  });

  // This is currently failing due to issues with Vue's handling of whitespace
  test.skip.each([
    ['preserves whitespace when annotation contains only whitespace',
     '
foo%sbar
', [' '],
     [{...DEFAULT_ANNOTATION, start_paragraph: 1, end_paragraph: 1, start_offset: 3, end_offset: 4}]]
  ])('%s', (testTitle, sectionHTML, toSelect, annotations) => {
    store.commit('annotations/append', annotations);
    const wrapper = mount(ResourceSection, {store, localVue, propsData: {
      index: 1,
      el: parseHTML(util.format(sectionHTML, ...toSelect))
    }});
    expect(wrapper.findAll(`.selected-text`).wrappers.map(w => parseHTML(w.html()).innerHTML)).toEqual(toSelect);
  });

  test.todo('when rendering, orders annotations first by length (longer wraps shorter)');
  test.todo('when rendering, orders annotations second by time (newer wraps older)');
});
<|endoftext|>


<commit_before>//<script src="vexflow-min.js"></script>

(function(Score) {

Score.Stave = function(canvasId, clef_name, time_signature) {
   var self = this;

   self._clef_name = clef_name;
   self._canvas = document.getElementById(canvasId);
   self._renderer = new Vex.Flow.Renderer(self._canvas, Vex.Flow.Renderer.Backends.CANVAS);
   self._ctx = self._renderer.getContext();
   self._width = self._canvas.width-10;
   self._stave = new Vex.Flow.Stave(5, 10, self._width);
   self._stave.addClef(clef_name);
   if (time_signature) {
      self._stave.addTimeSignature(time_signature);
   }
   self._stave.setContext(self._ctx);
   self._stave.draw();
};

Score.Stave.prototype.clear = function() {
   var self = this;
   self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);
   self._stave.draw();
};

Score.Stave.prototype.drawBeat = function(notes, duration, annotation) {
   var self = this;

   var voice_notes = new Vex.Flow.Voice({ num_beats: 1, beat_value: duration, resolution: Vex.Flow.RESOLUTION });
   voice_notes.addTickables([self._makeBeat(notes, duration)]);

   var text_notes = new Vex.Flow.Voice({ num_beats: 1, beat_value: duration, resolution: Vex.Flow.RESOLUTION });
   text_notes.addTickables([self._beatAnnotation(duration, annotation)]);

   self._draw(voice_notes, text_notes);
};

Score.Stave.prototype.drawSequence = function(beats) {
   var self = this;

   var seq = self._makeSequence(beats);

   var voice_notes = new Vex.Flow.Voice({ num_beats: seq.num_beats, beat_value: seq.beat_value, resolution: Vex.Flow.RESOLUTION });
   voice_notes.addTickables(seq.notes);

   var text_notes = new Vex.Flow.Voice({ num_beats: seq.num_beats, beat_value: seq.beat_value, resolution: Vex.Flow.RESOLUTION });
   text_notes.addTickables(seq.annotation);

   self._draw(voice_notes, text_notes);
};

Score.Stave.prototype._draw = function(voice, annotation) {
   var self = this;
   self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);
   var formatter = new Vex.Flow.Formatter().joinVoices([voice, annotation]).format([voice, annotation], self._width);
   self._stave.draw();
   voice.draw(self._ctx, self._stave);
   annotation.draw(self._ctx, self._stave);
};

Score.Stave.prototype._makeBeat = function(notes, duration) {
   var self = this;

   var keys = [];
   notes.forEach(function (note_info) {
      keys.push(note_info.name+"/"+(note_info.octave || '4'));
   });

   var stave_note = new Vex.Flow.StaveNote({ keys: keys, duration: duration.toString(), clef: self._clef_name, auto_stem: true });

   for (var i = 0; i < notes.length; ++i) {
      if (notes[i].accidental) {
         stave_note.addAccidental(i, new Vex.Flow.Accidental(notes[i].accidental));
      }
      if (notes[i].color) {
         stave_note.setKeyStyle(i, {strokeStyle: notes[i].color, fillStyle: notes[i].color});
      }
   }
   return stave_note;
};

Score.Stave.prototype._beatAnnotation = function(duration, annotation) {
   var self = this;
   var annotation = annotation || {text: '', position: 0};
   var text_note = new Vex.Flow.TextNote({ text: annotation.text,
                                           font: {family: 'Arial', size: 10, weight: ''},
                                           duration: duration.toString() }).setLine(annotation.position).setJustification(Vex.Flow.TextNote.Justification.LEFT).setContext(self._ctx);
   return text_note;
};

Score.Stave.prototype._makeSequence = function(beats) {
   var self = this;

   var stave_notes = [];
   var text_notes = [];
   var total_duration = 0;
   beats.forEach(function (beat_info) {
      stave_notes.push(self._makeBeat(beat_info.notes, beat_info.duration));
      text_notes.push(self._beatAnnotation(beat_info.duration, beat_info.annotation));
      total_duration += 32/beat_info.duration;
   });

   return {notes: stave_notes, num_beats: total_duration, beat_value: 32, annotation: text_notes};
};

}(window.Score = window.Score || {}));

<commit_msg>Great Staves and Key Signatures<commit_after>//<script src="vexflow-min.js"></script>
//   KeySignature:
//	  MAJOR_KEYS:
//	    "C"
//	    "F"
//	    "Bb"
//	    "Eb"
//	    "Ab"
//	    "Db"
//	    "Gb"
//	    "Cb"
//	    "G"
//	    "D"
//	    "A"
//	    "E"
//	    "B"
//	    "F#"
//	    "C#"
//
//	  MINOR_KEYS:
//	    "Am"
//	    "Dm"
//	    "Gm"
//	    "Cm"
//	    "Fm"
//	    "Bbm"
//	    "Ebm"
//	    "Abm"
//	    "Em"
//	    "Bm"
//	    "F#m"
//	    "C#m"
//	    "G#m"
//	    "D#m"
//	    "A#m"

(function(Score) {

Score._makeStave = function(ctx, clef_name, y_position, width, time_signature, key_signature) {
   var stave = new Vex.Flow.Stave(5, y_position, width);
   stave.addClef(clef_name);
   if (time_signature) {
      stave.addTimeSignature(time_signature);
   }
   stave.addKeySignature(key_signature || "C");
   stave.setContext(ctx);
   stave.draw();
   return stave;
};

Score._makeBeat = function(clef_name, notes, duration) {
   var keys = [];
   notes.forEach(function (note_info) {
      keys.push(note_info.name+"/"+(note_info.octave || '4'));
   });

   var stave_note = new Vex.Flow.StaveNote({ keys: keys, duration: duration.toString(), clef: clef_name, auto_stem: true });

   for (var i = 0; i < notes.length; ++i) {
      if (notes[i].accidental) {
         stave_note.addAccidental(i, new Vex.Flow.Accidental(notes[i].accidental));
      }
      if (notes[i].color) {
         stave_note.setKeyStyle(i, {strokeStyle: notes[i].color, fillStyle: notes[i].color});
      }
   }
   return stave_note;
};

Score._beatAnnotation = function(ctx, duration, annotation) {
   var annotation = annotation || {text: '', position: 0};
   var text_note = new Vex.Flow.TextNote({ text: annotation.text,
                                           font: {family: 'Arial', size: 10, weight: ''},
                                           duration: duration.toString() }).setLine(annotation.position).setJustification(Vex.Flow.TextNote.Justification.LEFT).setContext(ctx);
   return text_note;
};

Score._makeSequence = function(clef_name, ctx, beats) {
   var stave_notes = [];
   var text_notes = [];
   var total_duration = 0;
   beats.forEach(function (beat_info) {
      stave_notes.push(Score._makeBeat(clef_name, beat_info.notes, beat_info.duration));
      text_notes.push(Score._beatAnnotation(ctx, beat_info.duration, beat_info.annotation));
      total_duration += 32/beat_info.duration;
   });

   return {notes: stave_notes, num_beats: total_duration, beat_value: 32, annotation: text_notes};
};

Score._makeVoices  = function(clef_name, ctx, beats) {
   var seq = Score._makeSequence(clef_name, ctx, beats);
   var voice_notes = new Vex.Flow.Voice({ num_beats: seq.num_beats, beat_value: seq.beat_value, resolution: Vex.Flow.RESOLUTION });
   voice_notes.addTickables(seq.notes);

   var text_notes = new Vex.Flow.Voice({ num_beats: seq.num_beats, beat_value: seq.beat_value, resolution: Vex.Flow.RESOLUTION });
   text_notes.addTickables(seq.annotation);

   return {tones: voice_notes, text: text_notes};
};

Score.Stave = function(canvasId, clef_name, time_signature, key_signature) {
   var self = this;

   self._clef_name = clef_name;
   self._canvas = document.getElementById(canvasId);
   self._renderer = new Vex.Flow.Renderer(self._canvas, Vex.Flow.Renderer.Backends.CANVAS);
   self._ctx = self._renderer.getContext();
   self._width = self._canvas.width-10;
   self._stave = Score._makeStave(self._ctx, clef_name, 10, self._width, time_signature, key_signature);
};

Score.Stave.prototype.clear = function() {
   var self = this;
   self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);
   self._stave.draw();
};

Score.Stave.prototype.drawBeat = function(notes, duration, annotation) {
   var self = this;

   var voice_notes = new Vex.Flow.Voice({ num_beats: 1, beat_value: duration, resolution: Vex.Flow.RESOLUTION });
   voice_notes.addTickables([Score._makeBeat(self._clef_name, notes, duration)]);

   var text_notes = new Vex.Flow.Voice({ num_beats: 1, beat_value: duration, resolution: Vex.Flow.RESOLUTION });
   text_notes.addTickables([Score._beatAnnotation(self._ctx, duration, annotation)]);

   self._draw(voice_notes, text_notes);
};

Score.Stave.prototype.drawSequence = function(beats) {
   var self = this;
   var voices = Score._makeVoices(self._clef_name, self._ctx, beats);
   self._draw(voices.tones, voices.text);
};

Score.Stave.prototype._draw = function(voice, annotation) {
   var self = this;
   self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);
   var formatter = new Vex.Flow.Formatter().joinVoices([voice, annotation]).format([voice, annotation], self._width);
   self._stave.draw();
   voice.draw(self._ctx, self._stave);
   annotation.draw(self._ctx, self._stave);
};

Score.GreatStave = function(canvasId, time_signature, key_signature) {
   var self = this;

   self._canvas = document.getElementById(canvasId);
   self._renderer = new Vex.Flow.Renderer(self._canvas, Vex.Flow.Renderer.Backends.CANVAS);
   self._ctx = self._renderer.getContext();
   self._width = self._canvas.width-10;

   self._treble_stave = Score._makeStave(self._ctx, "treble", 10, self._width, time_signature, key_signature);
   self._bass_stave = Score._makeStave(self._ctx, "bass", 100, self._width, time_signature, key_signature);
   self._brace = new Vex.Flow.StaveConnector(self._treble_stave, self._bass_stave);
   self._brace.setType(Vex.Flow.StaveConnector.type.BRACKET);
   self._brace.setContext(self._ctx);
};

Score.GreatStave.prototype.clear = function() {
   var self = this;
   self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);
   self._treble_stave.draw();
   self._bass_stave.draw();
   self._brace.draw();
};

Score.GreatStave.prototype.sequence = function(treble_beats, bass_beats) {
   var self = this;
   var treble_voices = Score._makeVoices("treble", self._ctx, treble_beats);
   var bass_voices = Score._makeVoices("bass", self._ctx, bass_beats);

   self._ctx.clearRect(0, 0, self._canvas.width, self._canvas.height);

   var formatter = new Vex.Flow.Formatter();
   formatter.joinVoices([treble_voices.tones, treble_voices.text]);
   formatter.joinVoices([bass_voices.tones, bass_voices.text]);
   formatter.format([treble_voices.tones, bass_voices.tones, treble_voices.text, bass_voices.text], self._width);

   self._treble_stave.draw();
   self._bass_stave.draw();
   self._brace.draw();
   treble_voices.tones.draw(self._ctx, self._treble_stave);
   treble_voices.text.draw(self._ctx, self._treble_stave);
   bass_voices.tones.draw(self._ctx, self._bass_stave);
   bass_voices.text.draw(self._ctx, self._bass_stave);
};

}(window.Score = window.Score || {}));

<|endoftext|>


<commit_before>var creep_assattacker = {

    /** @param {Creep} creep **/
    run: function(creep) {

        var unboostedTough = 0;
        var unboostedAttack = 0;
        var unboostedMove = 0;
        var unboostedWork = 0;
        var unboostedRanged = 0;

        creep.body.forEach(function(thisPart) {
            if (thisPart.type == ATTACK && !thisPart.boost) {
                unboostedAttack = unboostedAttack + 1;
            } else if (thisPart.type == TOUGH && !thisPart.boost) {
                unboostedTough = unboostedTough + 1;
            } else if (thisPart.type == MOVE && !thisPart.boost) {
                unboostedMove = unboostedMove + 1;
            } else if (thisPart.type == WORK && !thisPart.boost) {
                unboostedWork = unboostedWork + 1;
            } else if (thisPart.type == RANGED_ATTACK && !thisPart.boost) {
                unboostedRanged = unboostedRanged + 1;
            }
        });

        if (!creep.memory.healerID && !creep.spawning) {
            var nearbyHealer = creep.pos.findInRange(FIND_MY_CREEPS, 2, {
                filter: (mCreep) => (mCreep.memory.priority == "asshealer" && mCreep.memory.attackerID == creep.id)
            });
            if (nearbyHealer.length) {
                creep.memory.healerID = nearbyHealer[0].id;
            }
        }

        var closeFoe = creep.pos.findClosestByRange(FIND_HOSTILE_CREEPS, {
            filter: (eCreep) => (!Memory.whiteList.includes(eCreep.owner.username) && eCreep.owner.username != 'Eiskalt')
        });

        var thisHealer = Game.getObjectById(creep.memory.healerID);
        var healerIsNear = false;
        if (thisHealer) {
            healerIsNear = creep.pos.isNearTo(thisHealer);
        }

        if (Game.flags["DoBoost"] && unboostedMove > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var MoveLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_ZYNTHIUM_ALKALIDE)
            });
            if (MoveLab.length && MoveLab[0].mineralAmount > 0) {
                creep.travelTo(MoveLab[0]);
                MoveLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedTough > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var ToughLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_GHODIUM_ALKALIDE)
            });
            if (ToughLab.length && ToughLab[0].mineralAmount > 0) {
                creep.travelTo(ToughLab[0], {
                    ignoreRoads: true
                });
                ToughLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedAttack > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var AttackLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_UTRIUM_ACID)
            });
            if (AttackLab.length && AttackLab[0].mineralAmount > 0) {
                creep.travelTo(AttackLab[0], {
                    ignoreRoads: true
                });
                AttackLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedWork > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var WorkLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_ZYNTHIUM_ACID)
            });
            if (WorkLab.length && WorkLab[0].mineralAmount > 0) {
                creep.travelTo(WorkLab[0], {
                    ignoreRoads: true
                });
                WorkLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedRanged > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var RangedLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_KEANIUM_ALKALIDE)
            });
            if (RangedLab.length && RangedLab[0].mineralAmount > 0) {
                creep.travelTo(RangedLab[0], {
                    ignoreRoads: true
                });
                RangedLab[0].boostCreep(creep);
            }
        } else {
            if (Game.flags[creep.memory.homeRoom + "Assault"] && Game.flags[creep.memory.homeRoom + "Assault"].pos && Game.flags[creep.memory.homeRoom + "Assault"].pos.roomName == creep.pos.roomName) {
                //In target room
                var somethingNearby = creep.pos.findClosestByRange(FIND_STRUCTURES);
                if (somethingNearby) {
                    creep.dismantle(somethingNearby);
                }

                creep.rangedMassAttack();
                if (creep.hits < creep.hitsMax - 700 && Game.flags["FallBack"] && Game.flags["FallBack"].pos) {
                    //Fall back
                    creep.travelTo(Game.flags["FallBack"], {
                        ignoreRoads: true
                    });
                } else if (!healerIsNear) {
                    if (creep.pos.x == 0 || creep.pos.x == 49 || creep.pos.y == 0 || creep.pos.y == 49) {
                        var xTarget = 0;
                        var yTarget = 0;
                        if (creep.pos.x == 0) {
                            xTarget = 2;
                            yTarget = creep.pos.y;
                        } else if (creep.pos.x == 49) {
                            xTarget = 47;
                            yTarget = creep.pos.y;
                        }
                        if (creep.pos.y == 0) {
                            yTarget = 2;
                            xTarget = creep.pos.x;
                        } else if (creep.pos.y == 49) {
                            yTarget = 47;
                            xTarget = creep.pos.x;
                        }
                        creep.moveTo(xTarget, yTarget);
                    }
                } else if (healerIsNear) {
                    if (Game.flags["WallFlag"]) {
                        var thisWall = Game.flags["WallFlag"].pos.lookFor(LOOK_STRUCTURES);
                        if (thisWall.length) {
                            creep.travelTo(thisWall[0], {
                                maxRooms: 1
                            });
                            creep.dismantle(thisWall[0]);
                        } else {
                            Game.flags["WallFlag"].remove();
                        }
                    } else {
                        var eSpawns = creep.room.find(FIND_HOSTILE_SPAWNS)
                        if (eSpawns.length) {
                            creep.travelTo(eSpawns[0], {
                                ignoreRoads: true,
                                maxRooms: 1
                            });
                            creep.dismantle(eSpawns[0]);
                        } else {
                            var eStructures = creep.pos.findClosestByRange(FIND_HOSTILE_STRUCTURES, {
                                filter: (structure) => (structure.structureType != STRUCTURE_CONTROLLER && structure.structureType != STRUCTURE_WALL && structure.structureType != STRUCTURE_RAMPART && structure.structureType != STRUCTURE_KEEPER_LAIR && structure.structureType != STRUCTURE_EXTRACTOR)
                            });
                            if (eStructures) {
                                creep.travelTo(eStructures, {
                                    ignoreRoads: true,
                                    maxRooms: 1
                                });
                                creep.dismantle(eStructures);
                            } else if (closeFoe) {
                                creep.travelTo(closeFoe, {
                                    ignoreRoads: true,
                                    maxRooms: 1
                                });
                                creep.attack(closeFoe);
                            } else if (Game.flags[creep.memory.homeRoom + "Assault"]) {
                                Game.flags[creep.memory.homeRoom + "Assault"].remove();
                            }
                        }

                    }
                }
            } else if (!healerIsNear) {
                if (creep.memory.getOutOfStartRoom) {
                    var thisPortal = undefined;
                    if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName == creep.pos.roomName) {
                        var thisPortal = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                            filter: (structure) => (structure.structureType == STRUCTURE_PORTAL)
                        });
                    }
                    if (thisPortal) {
                        creep.memory.destination = undefined;
                        creep.memory.usedPortal = true;
                        creep.travelTo(thisPortal);
                    } else if (creep.pos.x == 0 || creep.pos.x == 49 || creep.pos.y == 0 || creep.pos.y == 49) {
                        var xTarget = 0;
                        var yTarget = 0;
                        if (creep.pos.x == 0) {
                            xTarget = 2;
                            yTarget = creep.pos.y;
                        } else if (creep.pos.x == 49) {
                            xTarget = 47;
                            yTarget = creep.pos.y;
                        }
                        if (creep.pos.y == 0) {
                            yTarget = 2;
                            xTarget = creep.pos.x;
                        } else if (creep.pos.y == 49) {
                            yTarget = 47;
                            xTarget = creep.pos.x;
                        }
                        creep.moveTo(xTarget, yTarget);
                    }
                } else if (Game.flags["RallyHere"] && Game.flags["RallyHere"].pos) {
                    creep.travelTo(Game.flags["RallyHere"], {
                        ignoreRoads: true
                    });
                }
            } else if (healerIsNear) {
                if (!creep.memory.getOutOfStartRoom) {
                    creep.memory.getOutOfStartRoom = true;
                }
                if (creep.memory.usedPortal == undefined) {
                    creep.memory.usedPortal = false
                }
                if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName != creep.pos.roomName) {
                    creep.memory.destination = Game.flags["TakePortal"].pos.roomName;
                }

                var thisPortal = undefined;
                if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName == creep.pos.roomName) {
                    var thisPortal = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                        filter: (structure) => (structure.structureType == STRUCTURE_PORTAL)
                    });
                }
                if (thisPortal) {
                    creep.memory.destination = undefined;
                    creep.memory.usedPortal = true;
                    if (creep.memory.path && creep.memory.path.length && creep.memory.path[0] == creep.room.name) {
                        creep.memory.path.splice(0, 1);
                    }
                    creep.travelTo(thisPortal, {
                        ignoreRoads: true
                    });
                } else if (Game.flags[creep.memory.homeRoom + "Assault"] && Game.flags[creep.memory.homeRoom + "Assault"].pos.roomName != creep.pos.roomName) {
                    /*if (creep.memory.destination && !creep.memory.usedPortal) {
                        creep.travelTo(new RoomPosition(25, 25, creep.memory.destination))
                    } else*/
                    if (creep.memory.path && creep.memory.path.length) {
                        if (creep.memory.path[0] == creep.room.name) {
                            creep.memory.path.splice(0, 1);
                        }
                        creep.travelTo(new RoomPosition(25, 25, creep.memory.path[0]), {
                            ignoreRoads: true
                        });
                    } else if (Game.flags[creep.memory.homeRoom + "Assault"].pos) {
                        creep.travelTo(Game.flags[creep.memory.homeRoom + "Assault"], {
                            ignoreRoads: true
                        });
                    } else {
                        creep.travelTo(new RoomPosition(25, 25, Game.flags[creep.memory.homeRoom + "Assault"].pos.roomName), {
                            ignoreRoads: true
                        });
                    }
                }
            }
        }

        if (closeFoe) {
            creep.rangedMassAttack();
            //prioritize foebashing
            /*var found = closeFoe.pos.lookFor(LOOK_STRUCTURES);
            var hasRampart = false;
            for (var building in found) {
                if (found[building].structureType == STRUCTURE_RAMPART) {
                    hasRampart = true;
                    break;
                }
            }
            if (!hasRampart) {
                creep.attack(closeFoe);
            }*/
        }

    }

};

module.exports = creep_assattacker;
<commit_msg>Back to MoveTo<commit_after>var creep_assattacker = {

    /** @param {Creep} creep **/
    run: function(creep) {

        var unboostedTough = 0;
        var unboostedAttack = 0;
        var unboostedMove = 0;
        var unboostedWork = 0;
        var unboostedRanged = 0;

        creep.body.forEach(function(thisPart) {
            if (thisPart.type == ATTACK && !thisPart.boost) {
                unboostedAttack = unboostedAttack + 1;
            } else if (thisPart.type == TOUGH && !thisPart.boost) {
                unboostedTough = unboostedTough + 1;
            } else if (thisPart.type == MOVE && !thisPart.boost) {
                unboostedMove = unboostedMove + 1;
            } else if (thisPart.type == WORK && !thisPart.boost) {
                unboostedWork = unboostedWork + 1;
            } else if (thisPart.type == RANGED_ATTACK && !thisPart.boost) {
                unboostedRanged = unboostedRanged + 1;
            }
        });

        if (!creep.memory.healerID && !creep.spawning) {
            var nearbyHealer = creep.pos.findInRange(FIND_MY_CREEPS, 2, {
                filter: (mCreep) => (mCreep.memory.priority == "asshealer" && mCreep.memory.attackerID == creep.id)
            });
            if (nearbyHealer.length) {
                creep.memory.healerID = nearbyHealer[0].id;
            }
        }

        var closeFoe = creep.pos.findClosestByRange(FIND_HOSTILE_CREEPS, {
            filter: (eCreep) => (!Memory.whiteList.includes(eCreep.owner.username) && eCreep.owner.username != 'Eiskalt')
        });

        var thisHealer = Game.getObjectById(creep.memory.healerID);
        var healerIsNear = false;
        if (thisHealer) {
            healerIsNear = creep.pos.isNearTo(thisHealer);
        }

        if (Game.flags["DoBoost"] && unboostedMove > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var MoveLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_ZYNTHIUM_ALKALIDE)
            });
            if (MoveLab.length && MoveLab[0].mineralAmount > 0) {
                creep.travelTo(MoveLab[0]);
                MoveLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedTough > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var ToughLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_GHODIUM_ALKALIDE)
            });
            if (ToughLab.length && ToughLab[0].mineralAmount > 0) {
                creep.travelTo(ToughLab[0], {
                    ignoreRoads: true
                });
                ToughLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedAttack > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var AttackLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_UTRIUM_ACID)
            });
            if (AttackLab.length && AttackLab[0].mineralAmount > 0) {
                creep.travelTo(AttackLab[0], {
                    ignoreRoads: true
                });
                AttackLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedWork > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var WorkLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_ZYNTHIUM_ACID)
            });
            if (WorkLab.length && WorkLab[0].mineralAmount > 0) {
                creep.travelTo(WorkLab[0], {
                    ignoreRoads: true
                });
                WorkLab[0].boostCreep(creep);
            }
        } else if (Game.flags["DoBoost"] && unboostedRanged > 0 && Game.flags[creep.memory.homeRoom + "Assault"]) {
            var RangedLab = creep.room.find(FIND_MY_STRUCTURES, {
                filter: (structure) => (structure.structureType == STRUCTURE_LAB && structure.mineralType == RESOURCE_CATALYZED_KEANIUM_ALKALIDE)
            });
            if (RangedLab.length && RangedLab[0].mineralAmount > 0) {
                creep.travelTo(RangedLab[0], {
                    ignoreRoads: true
                });
                RangedLab[0].boostCreep(creep);
            }
        } else {
            if (Game.flags[creep.memory.homeRoom + "Assault"] && Game.flags[creep.memory.homeRoom + "Assault"].pos && Game.flags[creep.memory.homeRoom + "Assault"].pos.roomName == creep.pos.roomName) {
                //In target room
                var somethingNearby = creep.pos.findClosestByRange(FIND_STRUCTURES);
                if (somethingNearby) {
                    creep.dismantle(somethingNearby);
                }

                creep.rangedMassAttack();
                if (creep.hits < creep.hitsMax - 700 && Game.flags["FallBack"] && Game.flags["FallBack"].pos) {
                    //Fall back
                    creep.travelTo(Game.flags["FallBack"], {
                        ignoreRoads: true
                    });
                } else if (!healerIsNear) {
                    if (creep.pos.x == 0 || creep.pos.x == 49 || creep.pos.y == 0 || creep.pos.y == 49) {
                        var xTarget = 0;
                        var yTarget = 0;
                        if (creep.pos.x == 0) {
                            xTarget = 2;
                            yTarget = creep.pos.y;
                        } else if (creep.pos.x == 49) {
                            xTarget = 47;
                            yTarget = creep.pos.y;
                        }
                        if (creep.pos.y == 0) {
                            yTarget = 2;
                            xTarget = creep.pos.x;
                        } else if (creep.pos.y == 49) {
                            yTarget = 47;
                            xTarget = creep.pos.x;
                        }
                        creep.moveTo(xTarget, yTarget);
                    }
                } else if (healerIsNear) {
                    if (Game.flags["WallFlag"]) {
                        var thisWall = Game.flags["WallFlag"].pos.lookFor(LOOK_STRUCTURES);
                        if (thisWall.length) {
                            creep.travelTo(thisWall[0], {
                                maxRooms: 1
                            });
                            creep.dismantle(thisWall[0]);
                        } else {
                            Game.flags["WallFlag"].remove();
                        }
                    } else {
                        var eSpawns = creep.room.find(FIND_HOSTILE_SPAWNS)
                        if (eSpawns.length) {
                            creep.travelTo(eSpawns[0], {
                                ignoreRoads: true,
                                maxRooms: 1
                            });
                            creep.dismantle(eSpawns[0]);
                        } else {
                            var eStructures = creep.pos.findClosestByRange(FIND_HOSTILE_STRUCTURES, {
                                filter: (structure) => (structure.structureType != STRUCTURE_CONTROLLER && structure.structureType != STRUCTURE_WALL && structure.structureType != STRUCTURE_RAMPART && structure.structureType != STRUCTURE_KEEPER_LAIR && structure.structureType != STRUCTURE_EXTRACTOR)
                            });
                            if (eStructures) {
                                creep.travelTo(eStructures, {
                                    ignoreRoads: true,
                                    maxRooms: 1
                                });
                                creep.dismantle(eStructures);
                            } else if (closeFoe) {
                                creep.moveTo(closeFoe, {
                                    ignoreRoads: true,
                                    maxRooms: 1
                                });
                                creep.attack(closeFoe);
                            } else if (Game.flags[creep.memory.homeRoom + "Assault"]) {
                                Game.flags[creep.memory.homeRoom + "Assault"].remove();
                            }
                        }

                    }
                }
            } else if (!healerIsNear) {
                if (creep.memory.getOutOfStartRoom) {
                    var thisPortal = undefined;
                    if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName == creep.pos.roomName) {
                        var thisPortal = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                            filter: (structure) => (structure.structureType == STRUCTURE_PORTAL)
                        });
                    }
                    if (thisPortal) {
                        creep.memory.destination = undefined;
                        creep.memory.usedPortal = true;
                        creep.travelTo(thisPortal);
                    } else if (creep.pos.x == 0 || creep.pos.x == 49 || creep.pos.y == 0 || creep.pos.y == 49) {
                        var xTarget = 0;
                        var yTarget = 0;
                        if (creep.pos.x == 0) {
                            xTarget = 2;
                            yTarget = creep.pos.y;
                        } else if (creep.pos.x == 49) {
                            xTarget = 47;
                            yTarget = creep.pos.y;
                        }
                        if (creep.pos.y == 0) {
                            yTarget = 2;
                            xTarget = creep.pos.x;
                        } else if (creep.pos.y == 49) {
                            yTarget = 47;
                            xTarget = creep.pos.x;
                        }
                        creep.moveTo(xTarget, yTarget);
                    }
                } else if (Game.flags["RallyHere"] && Game.flags["RallyHere"].pos) {
                    creep.travelTo(Game.flags["RallyHere"], {
                        ignoreRoads: true
                    });
                }
            } else if (healerIsNear) {
                if (!creep.memory.getOutOfStartRoom) {
                    creep.memory.getOutOfStartRoom = true;
                }
                if (creep.memory.usedPortal == undefined) {
                    creep.memory.usedPortal = false
                }
                if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName != creep.pos.roomName) {
                    creep.memory.destination = Game.flags["TakePortal"].pos.roomName;
                }

                var thisPortal = undefined;
                if (Game.flags["TakePortal"] && Game.flags["TakePortal"].pos.roomName == creep.pos.roomName) {
                    var thisPortal = creep.pos.findClosestByRange(FIND_STRUCTURES, {
                        filter: (structure) => (structure.structureType == STRUCTURE_PORTAL)
                    });
                }
                if (thisPortal) {
                    creep.memory.destination = undefined;
                    creep.memory.usedPortal = true;
                    if (creep.memory.path && creep.memory.path.length && creep.memory.path[0] == creep.room.name) {
                        creep.memory.path.splice(0, 1);
                    }
                    creep.travelTo(thisPortal, {
                        ignoreRoads: true
                    });
                } else if (Game.flags[creep.memory.homeRoom + "Assault"] && Game.flags[creep.memory.homeRoom + "Assault"].pos.roomName != creep.pos.roomName) {
                    /*if (creep.memory.destination && !creep.memory.usedPortal) {
                        creep.travelTo(new RoomPosition(25, 25, creep.memory.destination))
                    } else*/
                    if (creep.memory.path && creep.memory.path.length) {
                        if (creep.memory.path[0] == creep.room.name) {
                            creep.memory.path.splice(0, 1);
                        }
                        creep.travelTo(new RoomPosition(25, 25, creep.memory.path[0]), {
                            ignoreRoads: true
                        });
                    } else if (Game.flags[creep.memory.homeRoom + "Assault"].pos) {
                        creep.travelTo(Game.flags[creep.memory.homeRoom + "Assault"], {
                            ignoreRoads: true
                        });
                    } else {
                        creep.travelTo(new RoomPosition(25, 25, Game.flags[creep.memory.homeRoom + "Assault"].pos.roomName), {
                            ignoreRoads: true
                        });
                    }
                }
            }
        }

        if (closeFoe) {
            creep.rangedMassAttack();
            //prioritize foebashing
            /*var found = closeFoe.pos.lookFor(LOOK_STRUCTURES);
            var hasRampart = false;
            for (var building in found) {
                if (found[building].structureType == STRUCTURE_RAMPART) {
                    hasRampart = true;
                    break;
                }
            }
            if (!hasRampart) {
                creep.attack(closeFoe);
            }*/
        }

    }

};

module.exports = creep_assattacker;
<|endoftext|>


<commit_before>'use strict';

var mean = require('meanio');

module.exports = function(System, app, auth, database) {

  // Home route
  var index = require('../controllers/index')(System);
  app.route('/')
    .get(index.render);
  app.route('/api/aggregatedassets')
    .get(index.aggregatedList);

  app.get('/*',function(req,res,next){
        res.header('workerID' , JSON.stringify(mean.options.workerid) );
        next(); // http://expressjs.com/guide.html#passing-route control
  });

  app.get('/api/get-public-config', function(req, res){
    var config = mean.loadConfigNew();
    return res.send(config.public);
  });
};
<commit_msg>Updated by adding all node modules<commit_after>'use strict';

var mean = require('meanio');

module.exports = function(System, app, auth, database) {

  // Home route
  var index = require('../controllers/index')(System);
  app.route('/')
    .get(index.render);
  app.route('/api/aggregatedassets')
    .get(index.aggregatedList);

  app.get('/*',function(req,res,next){
        res.header('workerID' , JSON.stringify(mean.options.workerid) );
        next(); // http://expressjs.com/guide.html#passing-route control
  });

  app.get('/api/get-public-config', function(req, res){

    var config = mean.loadConfigNew();

    mean.config.getSettings(req.query.name,config, function(error, doc) {
//        config = doc.settings;
    });
    return res.send(config.public);
  });
};
<|endoftext|>