<|start_filename|>desktop/store.test.js<|end_filename|>
const { SYNC_PERIOD } = require('./constants');
const { wait } = require('../shared/promise');
const { getPath } = require('../shared/object');
const path = require('path');
const os = require('os');
const fs = require('fs');
const { storeHandlers, ensureProjectFile } = require('./store');
const {
  ProjectState,
  Encrypt,
  DatabaseConnectorInfo,
  ServerInfo,
} = require('../shared/state');
const { ensureSigningKey } = require('./secret');

const makeProject = storeHandlers.filter(
  (r) => r.resource === 'makeProject'
)[0];
const getProject = storeHandlers.filter((r) => r.resource === 'getProject')[0];
const updateProject = storeHandlers.filter(
  (r) => r.resource === 'updateProject'
)[0];

test('write project with encrypted secrets, read with nulled secrets', async () => {
  // Shouldn't be harmful even though it is potentially creating a new
  // real file. It's value is valid and wouldn't overwrite an existing
  // one. Just necessary to call so that in tests this is definitely
  // populated.
  ensureSigningKey();

  const testProject = new ProjectState();
  const testServer = new ServerInfo();
  const testServerPassword = '<PASSWORD>';
  testServer.password_encrypt = new Encrypt(testServerPassword);
  const testServerPassphrase = '<PASSWORD>';
  testServer.passphrase_encrypt = new Encrypt(testServerPassphrase);
  const testDatabase = new DatabaseConnectorInfo();
  const testDatabasePassword = '<PASSWORD>';
  testDatabase.database.password_encrypt = new Encrypt(testDatabasePassword);
  testProject.servers.push(testServer);
  testProject.connectors.push(testDatabase);

  const projectId = 'unittestproject';
  const projectPath = ensureProjectFile(projectId);
  expect(projectPath).toBe(
    path.join(os.homedir(), 'DataStationProjects', projectId + '.dsproj')
  );

  try {
    await makeProject.handler(null, { projectId });
    await updateProject.handler(projectId, testProject);

    // Wait to make sure file has been written
    await wait(SYNC_PERIOD + 1000);

    const f = fs.readFileSync(projectPath);
    const onDisk = JSON.parse(f.toString());

    // Passwords are encrypted
    expect(onDisk.servers[0].password_encrypt.value.length).not.toBe(0);
    expect(onDisk.servers[0].password_encrypt.value).not.toBe(
      testServerPassword
    );
    expect(onDisk.servers[0].password_encrypt.encrypted).toBe(true);
    expect(onDisk.servers[0].passphrase_encrypt.value.length).not.toBe(0);
    expect(onDisk.servers[0].passphrase_encrypt.value).not.toBe(
      testServerPassphrase
    );
    expect(onDisk.servers[0].passphrase_encrypt.encrypted).toBe(true);
    expect(
      onDisk.connectors[0].database.password_encrypt.value.length
    ).not.toBe(0);
    expect(onDisk.connectors[0].database.password_encrypt.value).not.toBe(
      testDatabasePassword
    );
    expect(onDisk.connectors[0].database.password_encrypt.encrypted).toBe(true);

    // Passwords come back as null
    const readProject = await getProject.handler(null, { projectId });
    expect(readProject).toStrictEqual(ProjectState.fromJSON(testProject));
  } finally {
    try {
      fs.unlinkSync(projectPath);
    } catch (e) {
      console.error(e);
    }
  }
});

test('write project with encrypted secrets, read with nulled secrets', async () => {
  const testProject = new ProjectState();
  testProject.projectName = path.join(os.homedir(), 'unittestproject2.dsproj');

  try {
    await makeProject.handler(null, { projectId: testProject.projectName });
    const read = await getProject.handler(null, {
      projectId: testProject.projectName,
    });
    read.id = testProject.id; // id is generated newly on every instantiation which is ok
    expect(read).toStrictEqual(testProject);
  } finally {
    const projectPath = ensureProjectFile(testProject.projectName);
    try {
      fs.unlinkSync(projectPath);
    } catch (e) {
      console.error(e);
    }
  }
});


<|start_filename|>shared/languages/javascript.json<|end_filename|>
{
  "defaultPath": "node",
  "id": "javascript",
  "name": "JavaScript",
  "preamble": "\nfunction DM_getPanelFile(i) {\n  return '$$RESULTS_FILE$$'+$$JSON_ID_MAP$$[i];\n}\n\nfunction DM_getPanel(i) {\n  const fs = require('fs');\n  return JSON.parse(fs.readFileSync('$$RESULTS_FILE$$'+$$JSON_ID_MAP$$[i]));\n}\n\nfunction DM_setPanel(v) {\n  const fs = require('fs');\n  const fd = fs.openSync('$$PANEL_RESULTS_FILE$$', 'w');\n  if (Array.isArray(v)) {\n    fs.writeSync(fd, '[');\n    for (let i = 0; i < v.length; i++) {\n      const row = v[i];\n      let rowJSON = JSON.stringify(row);\n      if (i < v.length - 1) {\n        rowJSON += ',';\n      }\n      fs.writeSync(fd, rowJSON);\n    }\n    fs.writeSync(fd, ']');\n  } else {\n    fs.writeSync(fd, JSON.stringify(v));\n  }\n}"
}


<|start_filename|>server/auth.test.js<|end_filename|>
require('./auth');

test('stub', () => {});


<|start_filename|>server/rpc.test.js<|end_filename|>
const { handleRPC } = require('./rpc');

test('dispatching works', async () => {
  let done = false;

  const req = {
    query: {
      resource: 'test',
      projectId: 'my project',
      body: { abody: 'a thing' },
    },
    body: {},
  };

  const rsp = {
    json(msg) {
      expect(msg).toStrictEqual({ aresponse: true });
      done = true;
    },
  };

  const handlers = [
    {
      resource: 'test',
      handler: (projectId, body, dispatch, external) => {
        // TODO: test internal dispatch

        expect(projectId).toBe('my project');
        expect(body).toStrictEqual({ abody: 'a thing' });
        expect(typeof dispatch).toStrictEqual('function');
        expect(external).toStrictEqual(true);
        return { aresponse: true };
      },
    },
  ];

  await handleRPC(req, rsp, handlers);

  expect(done).toBe(true);
});


<|start_filename|>desktop/project.test.js<|end_filename|>
require('./project');

test('stub', () => {});


<|start_filename|>shared/text.test.js<|end_filename|>
const { title, humanSize, parseArrayBuffer } = require('./text');

test('title', () => {
  expect(title('ac_bd')).toBe('Ac Bd');
  expect(title('ac bd')).toBe('Ac Bd');
  expect(title('ac-bd')).toBe('Ac Bd');
  expect(title('ac-bd efgII')).toBe('Ac Bd Efgii');
});

test('humanSize', () => {
  expect(humanSize(80)).toBe('80B');
  expect(humanSize(1080)).toBe('1.08KB');
  expect(humanSize(1080_000)).toBe('1.08MB');
  expect(humanSize(1080_000_000)).toBe('1.08GB');
  expect(humanSize(1080_000_000_000)).toBe('1.08TB');
});

test('parse csv', async () => {
  // Explicit type
  let res = await parseArrayBuffer(
    { type: 'text/csv' },
    '',
    'name,age\nkev,12'
  );

  expect(res.contentType).toBe('text/csv');
  expect(res.value).toStrictEqual([{ name: 'kev', age: '12' }]);

  // And with only filename to guess
  res = await parseArrayBuffer(
    { type: '' },
    'test.csv',
    new TextEncoder('utf-8').encode('name,age\nkev,12')
  );

  expect(res.contentType).toBe('text/csv');
  expect(res.value).toStrictEqual([{ name: 'kev', age: '12' }]);
});

test('json newlines', async () => {
  const logs = [
    { a: 1, b: 23 },
    { a: 22, b: 90 },
  ];
  const res = await parseArrayBuffer(
    { type: 'application/jsonlines' },
    '',
    logs.map(JSON.stringify).join('\n')
  );

  expect(res.value).toStrictEqual(logs);
});

test('nginx regex', async () => {
  const sampleLogs = `172.16.31.10 - - [06/Nov/2014:19:10:38 +0600] "GET /news/53f8d72920ba2744fe873ebc.html HTTP/1.1" 404 177 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
192.168.3.11 - - [06/Nov/2014:19:12:14 +0600] "GET /?q=%E0%A6%A6%E0%A7%8B%E0%A7%9F%E0%A6%BE HTTP/1.1" 200 4356 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"`;

  const res = await parseArrayBuffer(
    { type: 'text/nginxaccess' },
    '',
    sampleLogs
  );

  expect(res.value.map((g) => ({ ...g }))).toStrictEqual([
    {
      remote: '172.16.31.10',
      host: '-',
      user: '-',
      time: '06/Nov/2014:19:10:38 +0600',
      method: 'GET',
      path: '/news/53f8d72920ba2744fe873ebc.html',
      code: '404',
      size: '177',
      referer: '-',
      agent:
        'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
      http_x_forwarded_for: undefined,
    },
    {
      remote: '192.168.3.11',
      host: '-',
      user: '-',
      time: '06/Nov/2014:19:12:14 +0600',
      method: 'GET',
      path: '/?q=%E0%A6%A6%E0%A7%8B%E0%A7%9F%E0%A6%BE',
      code: '200',
      size: '4356',
      referer: '-',
      agent:
        'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
      http_x_forwarded_for: undefined,
    },
  ]);
  expect(res.contentType).toBe('text/nginxaccess');
});


<|start_filename|>server/exportRenderer.test.js<|end_filename|>
const {
  ProjectState,
  PanelResultMeta,
  ProjectPage,
  TablePanelInfo,
} = require('../shared/state');
const { renderPage } = require('./exportRenderer');

const project = new ProjectState();
project.pages = [new ProjectPage()];
const tpi = new TablePanelInfo({
  columns: ['name', 'age'],
});
tpi.resultMeta = new PanelResultMeta({
  value: [
    { name: 'Kerry', age: 44 },
    { name: 'Monroe', age: 59 },
  ],
  lastRun: new Date(),
});
project.pages[0].panels = [tpi];

test('renders the project', () => {
  const html = renderPage(project, project.pages[0].id).replace('\n', '');
  expect(html.includes('<style type="text/css">')).toBe(true);
  // Only the table gets rendered
  expect(html.split(`className="panel-name"`).length).toBe(1);
  expect(html.split('Monroe').length).toBe(1);
  expect(html.split('Kerry').length).toBe(1);
});


<|start_filename|>desktop/rpc.test.js<|end_filename|>
const {
  RPC_ASYNC_REQUEST,
  RPC_ASYNC_RESPONSE,
} = require('../shared/constants');
const { registerRPCHandlers } = require('./rpc');

test('registers handlers', async () => {
  let handle;
  const ipcMain = {
    on(msg, h) {
      expect(msg).toBe(RPC_ASYNC_REQUEST);
      handle = h;
    },
  };

  let finished1 = false;
  const handlers = [
    {
      resource: 'test',
      handler: (projectId, body, dispatch, external) => {
        // TODO: test internal dispatch
        expect(projectId).toBe('test id');
        expect(body).toStrictEqual({ something: 1 });
        expect(external).toStrictEqual(true);
        expect(typeof dispatch).toBe('function');
        finished1 = true;
        return { aresponse: true };
      },
    },
  ];

  let finished2 = false;
  registerRPCHandlers(ipcMain, handlers);
  const event = {
    sender: {
      send(channel, body) {
        expect(channel).toBe(`${RPC_ASYNC_RESPONSE}:88`);
        expect(body.kind).toBe('response');
        expect(body.body).toStrictEqual({ aresponse: true });
        finished2 = true;
      },
    },
  };
  await handle(event, {
    resource: 'test',
    messageNumber: 88,
    projectId: 'test id',
    body: { something: 1 },
  });

  if (!finished1 || !finished2) {
    throw new Error('Test did not finish.');
  }
});


<|start_filename|>shared/languages/r.json<|end_filename|>
{
  "defaultPath": "Rscript",
  "id": "r",
  "name": "R",
  "preamble": "\ntryCatch(library(\"rjson\"), error=function(cond) {\n  install.packages(\"rjson\", repos=\"https://cloud.r-project.org\")\n}, finally=library(\"rjson\"))\n\nDM_getPanel <- function(i) {\n  panelId = fromJSON(\"$$JSON_ID_MAP_QUOTE_ESCAPED$$\")[[toString(i)]]\n  fromJSON(file=paste(\"$$RESULTS_FILE$$\", panelId, sep=\"\"))\n}\n\nDM_setPanel <- function(v) {\n  write(toJSON(v), \"$$PANEL_RESULTS_FILE$$\")\n}\n\nDM_getPanelFile <- function(i) {\n  paste(\"$$RESULTS_FILE$$\", fromJSON(\"$$JSON_ID_MAP_QUOTE_ESCAPED$$\")[[toString(i)]], sep=\"\")\n}\n"
}


<|start_filename|>shared/languages/php.json<|end_filename|>
{
  "commandArgs": ["-d", "display_errors=on"],
  "defaultPath": "php",
  "id": "php",
  "name": "PHP",
  "preamble": "\n<?php\n\nfunction DM_getPanel($i) {\n  return json_decode(file_get_contents('$$RESULTS_FILE$$' . json_decode('$$JSON_ID_MAP$$', true)[strval($i)]), true);\n}\n\nfunction DM_setPanel($v) {\n  file_put_contents('$$PANEL_RESULTS_FILE$$', json_encode($v));\n}\n\nfunction DM_getPanelFile($i) {\n  return '$$RESULTS_FILE$$' . json_decode('$$JSON_ID_MAP$$', true)[strval($i)];\n}"
}


<|start_filename|>desktop/panel/filagg.test.js<|end_filename|>
const { format, subMinutes, subHours, startOfHour } = require('date-fns');
const { getProjectResultsFile } = require('../store');
const fs = require('fs');
const {
  LiteralPanelInfo,
  FilterAggregatePanelInfo,
} = require('../../shared/state');
const { makeEvalHandler } = require('./eval');
const { withSavedPanels, RUNNERS } = require('./testutil');

for (const subprocessName of RUNNERS) {
  // Only works with Go now
  if (!subprocessName?.go) {
    continue;
  }

  describe(`filagg tests via ${
    subprocessName ? subprocessName.node || subprocessName.go : 'same-process'
  }`, () => {
    const lp = new LiteralPanelInfo({
      contentTypeInfo: { type: 'application/json' },
      content: JSON.stringify([
        { age: 19, name: 'Kate' },
        { age: 20, name: 'Bake' },
        { age: 5, name: 'Dima' },
        { age: 5, name: 'Fateh' },
        { age: 9, name: 'Fei' },
      ]),
    });

    test('filters no group', async () => {
      const vp = new FilterAggregatePanelInfo({
        filter: 'age > 10',
        sortOn: 'age',
        panelSource: lp.id,
      });

      let finished = false;
      const panels = [lp, vp];
      await withSavedPanels(
        panels,
        async (project) => {
          const panelValueBuffer = fs.readFileSync(
            getProjectResultsFile(project.projectName) + vp.id
          );
          expect(JSON.parse(panelValueBuffer.toString())).toStrictEqual([
            { name: 'Bake', age: 20 },
            { name: 'Kate', age: 19 },
          ]);

          finished = true;
        },
        { evalPanels: true, subprocessName }
      );

      if (!finished) {
        throw new Error('Callback did not finish');
      }
    }, 30_000);

    test('filters with group', async () => {
      const vp = new FilterAggregatePanelInfo({
        filter: 'age < 10',
        sortOn: 'Aggregate: count',
        groupBy: 'age',
        aggregateType: 'count',
        panelSource: lp.id,
      });

      let finished = false;
      const panels = [lp, vp];
      await withSavedPanels(
        panels,
        async (project) => {
          const panelValueBuffer = fs.readFileSync(
            getProjectResultsFile(project.projectName) + vp.id
          );
          expect(JSON.parse(panelValueBuffer.toString())).toStrictEqual([
            { age: 5, count: 2 },
            { age: 9, count: 1 },
          ]);

          finished = true;
        },
        { evalPanels: true, subprocessName }
      );

      if (!finished) {
        throw new Error('Callback did not finish');
      }
    });

    test('filters time range', async () => {
      const rows = [45, 6, 5, 14, 35].map((timeOffset) => ({
        time: subMinutes(new Date(), timeOffset).toISOString(),
        value: timeOffset,
      }));
      const lp = new LiteralPanelInfo({
        contentTypeInfo: { type: 'application/json' },
        content: JSON.stringify(rows),
      });

      const vp = new FilterAggregatePanelInfo({
        sortOn: 'time',
        range: {
          field: 'time',
          rangeType: 'relative',
          relative: 'last-15-minutes',
        },
        panelSource: lp.id,
      });

      let finished = false;
      const panels = [lp, vp];
      await withSavedPanels(
        panels,
        async (project) => {
          const panelValueBuffer = fs.readFileSync(
            getProjectResultsFile(project.projectName) + vp.id
          );
          expect(JSON.parse(panelValueBuffer.toString())).toStrictEqual([
            rows[2],
            rows[1],
            rows[3],
          ]);

          finished = true;
        },
        { evalPanels: true, subprocessName }
      );

      if (!finished) {
        throw new Error('Callback did not finish');
      }
    });

    test('group on time range', async () => {
      const startDate = new Date('2021-02-01 05:00:00');
      const rows = [45, 15, 80, 220, 5, 200, 35, 210, 100].map(
        (timeOffset) => ({
          time: subMinutes(startDate, timeOffset).toISOString(),
          value: timeOffset,
        })
      );
      const lp = new LiteralPanelInfo({
        contentTypeInfo: { type: 'application/json' },
        content: JSON.stringify(rows),
      });

      const vp = new FilterAggregatePanelInfo({
        sortOn: 'time',
        groupBy: 'time',
        aggregateType: 'count',
        windowInterval: '60',
        panelSource: lp.id,
      });

      let finished = false;
      const panels = [lp, vp];
      await withSavedPanels(
        panels,
        async (project) => {
          const panelValueBuffer = fs.readFileSync(
            getProjectResultsFile(project.projectName) + vp.id
          );

          const expected = [
            { time: subHours(startDate, 1), count: 4 },
            { time: subHours(startDate, 2), count: 2 },
            { time: subHours(startDate, 4), count: 3 },
          ];
          expect(JSON.parse(panelValueBuffer.toString())).toStrictEqual(
            expected.map((row) => ({
              ...row,
              time: format(row.time, 'yyyy-MM-dd HH:mm:ss'),
            }))
          );

          finished = true;
        },
        { evalPanels: true, subprocessName }
      );

      if (!finished) {
        throw new Error('Callback did not finish');
      }
    });
  });
}


<|start_filename|>shared/languages/python.json<|end_filename|>
{
  "defaultPath": "python3",
  "id": "python",
  "name": "Python",
  "preamble": "\ndef DM_getPanelFile(i):\n  return r'$$RESULTS_FILE$$'+$$JSON_ID_MAP$$[str(i)]\n\ndef DM_getPanel(i):\n  import json\n  with open(r'$$RESULTS_FILE$$'+$$JSON_ID_MAP$$[str(i)]) as f:\n    return json.load(f)\n\ndef DM_setPanel(v):\n  import json\n  with open(r'$$PANEL_RESULTS_FILE$$', 'w') as f:\n    json.dump(v, f)"
}


<|start_filename|>shared/url.test.js<|end_filename|>
const { fullHttpURL, queryParameters } = require('./url');

describe('fullHttpUrl', () => {
  test('basics', () => {
    expect(fullHttpURL('')).toBe('http://localhost');
    expect(fullHttpURL('https://foo.com', null, 9090)).toBe('https://foo.com');
    expect(fullHttpURL('foo.com', null, 9090)).toBe('http://foo.com:9090');
    expect(fullHttpURL('https://foo.com:8080', null, 9090)).toBe(
      'https://foo.com:8080'
    );

    expect(fullHttpURL('foo.com:9090', null, 9090)).toBe('http://foo.com:9090');

    expect(fullHttpURL('https://foo.com', 8080, 9090)).toBe(
      'https://foo.com:8080'
    );
    expect(fullHttpURL('localhost')).toBe('http://localhost');
    expect(fullHttpURL('localhost', 443)).toBe('https://localhost');
    expect(fullHttpURL('localhost/foobar', 443)).toBe(
      'https://localhost/foobar'
    );
    expect(fullHttpURL('localhost/fluber')).toBe('http://localhost/fluber');
    expect(fullHttpURL('localhost/fluber', 20)).toBe(
      'http://localhost:20/fluber'
    );
  });
});

describe('queryParameters', () => {
  test('basics', () => {
    expect(queryParameters({ a: 1, b: 2, c: undefined })).toBe('a=1&b=2');
  });
});


<|start_filename|>server/runner.test.js<|end_filename|>
require('./runner');

test('stub', () => {});


<|start_filename|>shared/languages/julia.json<|end_filename|>
{
  "defaultPath": "julia",
  "id": "julia",
  "name": "Julia",
  "preamble": "\ntry\n    import JSON\ncatch e\n    import Pkg\n    Pkg.add(\"JSON\")\n    import JSON\nend\n\nfunction DM_getPanel(i)\n  panelId = JSON.parse(\"$$JSON_ID_MAP_QUOTE_ESCAPED$$\")[string(i)]\n  JSON.parsefile(string(\"$$RESULTS_FILE$$\", panelId))\nend\n\nfunction DM_setPanel(v)\n  open(\"$$PANEL_RESULTS_FILE$$\", \"w\") do f\n    JSON.print(f, v)\n  end\nend\n\nfunction DM_getPanelFile(i)\n  string(\"$$RESULTS_FILE$$\", JSON.parse(\"$$JSON_ID_MAP_QUOTE_ESCAPED$$\")[string(i)])\nend"
}


<|start_filename|>shared/log.test.js<|end_filename|>
const log = require('./log');

test('it logs', () => {
  log.logger.INFO = jest.fn();
  log.logger.ERROR = jest.fn();

  log.default.info('a', 'b', 'c');
  expect(log.logger.INFO.mock.calls[0][0]).toMatch(
    /\[INFO\] [0-9:.ZT-]+ a b c/
  );

  const e = new Error('my message');
  log.default.error('a', e, 'c');
  const words = log.logger.ERROR.mock.calls[0][0].split(' ');
  expect(words.filter((f) => f.length)).toStrictEqual([
    '[ERROR]',
    words[1], // Already tested it looks like a date,
    'a',
    'my',
    'message',
    'c',
    '\n',
    ...e.stack
      .split('\n')
      .slice(1)
      .join('\n')
      .split(' ')
      .filter((f) => f.length),
  ]);
});


<|start_filename|>shared/rpc.test.js<|end_filename|>
require('./rpc');

test('stub', () => {});


<|start_filename|>scripts/generate_log_data.js<|end_filename|>
const faker = require('faker');

const data = [];
for (let i = 0; i < 1000; i++) {
  data.push({
    url: faker.image.imageUrl(),
    time: faker.date.past(),
    status: faker.random.number({ min: 200, max: 500 }),
  });
}

console.log(JSON.stringify(data));


<|start_filename|>runner/http_test.go<|end_filename|>
package runner

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func Test_getHTTPHostPort(t *testing.T) {
	tests := []struct {
		url     string
		expTls  bool
		expHost string
		expPort string
		expErr  error
	}{
		{
			"localhost",
			false,
			"localhost",
			"80",
			nil,
		},
		{
			":80",
			false,
			"localhost",
			"80",
			nil,
		},
		{
			"http://localhost",
			false,
			"localhost",
			"80",
			nil,
		},
		{
			"https://localhost",
			true,
			"localhost",
			"443",
			nil,
		},
		{
			"https://foo.com",
			true,
			"foo.com",
			"443",
			nil,
		},
		{
			"https://foo.com:444",
			true,
			"foo.com",
			"444",
			nil,
		},
		{
			"foo.com:444",
			false,
			"foo.com",
			"444",
			nil,
		},
		{
			"/xyz",
			false,
			"localhost",
			"80",
			nil,
		},
		{
			":443/xyz",
			true,
			"localhost",
			"443",
			nil,
		},
		{
			":90/xyz",
			false,
			"localhost",
			"90",
			nil,
		},
	}

	for _, ts := range tests {
		tls, host, port, _, err := getHTTPHostPort(ts.url)
		assert.Equal(t, ts.expTls, tls, ts.url)
		assert.Equal(t, ts.expHost, host, ts.url)
		assert.Equal(t, ts.expPort, port, ts.url)
		assert.Equal(t, ts.expErr, err, ts.url)
	}
}


<|start_filename|>server/exporter.test.js<|end_filename|>
const {
  ProjectState,
  ProjectPage,
  ScheduledExport,
  TablePanelInfo,
  PanelResultMeta,
} = require('../shared/state');
const { main, fetchAndRunAllExports, Exporter } = require('./exporter');

const project = new ProjectState();
project.pages = [new ProjectPage()];
const tpi = new TablePanelInfo({
  columns: ['name', 'age'],
});
tpi.resultMeta = new PanelResultMeta({
  value: [
    { name: 'Kerry', age: 44 },
    { name: 'Monroe', age: 59 },
  ],
  lastRun: new Date(),
});
project.pages[0].panels = [tpi];

project.pages[0].schedules = [
  new ScheduledExport({
    destination: {
      type: 'email',
      from: '<EMAIL>',
      recipients: '<EMAIL>',
      server: 'smtp.test.com',
    },
  }),
  new ScheduledExport({
    period: 'week',
    destination: {
      type: 'email',
      from: '<EMAIL>',
      recipients: '<EMAIL>',
      server: 'smtp2.test.com',
    },
  }),
  new ScheduledExport({
    period: 'month',
    destination: {
      type: 'email',
      from: '<EMAIL>',
      recipients: '<EMAIL>',
      server: 'smtp3.test.com',
    },
  }),
];

test('getScheduledExports', () => {
  const e = new Exporter(() => {});
  const { daily, weekly, monthly } = e.getScheduledExports(project);
  expect(daily).toStrictEqual([
    [project, project.pages[0], project.pages[0].schedules[0]],
  ]);
  expect(weekly).toStrictEqual([
    [project, project.pages[0], project.pages[0].schedules[1]],
  ]);
  expect(monthly).toStrictEqual([
    [project, project.pages[0], project.pages[0].schedules[2]],
  ]);
});

describe('fetchAndRunAllExports', () => {
  const handlers = [
    {
      resource: 'getProjects',
      handler: () => [project],
    },
    {
      resource: 'getProject',
      handler: () => project,
    },
    {
      resource: 'eval',
      handler: () => {},
    },
  ];
  const dbpool = {
    connect() {
      return client;
    },
  };
  const transport = {
    sendMail: jest.fn(),
  };
  const nodemailer = {
    createTransport: jest.fn(() => transport),
  };
  const app = { migrate: jest.fn(), projectHandlers: handlers };
  beforeAll(async () => {
    await main(app, () => nodemailer, {
      daily: true,
      weekly: true,
      monthly: true,
    });
  });

  test('createTransport', () => {
    expect(nodemailer.createTransport.mock.calls.length).toBe(3);
  });

  test('sendMail', () => {
    expect(transport.sendMail.mock.calls.length).toBe(3);
  });
});


<|start_filename|>tsconfig.json<|end_filename|>
{
  "compilerOptions": {
    "noImplicitAny": true,
    "noUnusedLocals": true,
    "noEmit": true,
    "jsx": "react",
    "allowJs": true,
    "target": "esnext",
    "module": "commonjs",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "typeRoots": ["./node_modules/@types", "./type-overrides"],
    "resolveJsonModule": true
  },
  "exclude": ["node_modules", "*.js", "build"]
}


<|start_filename|>desktop/app.test.js<|end_filename|>
require('./app');

test('stub', () => {});


<|start_filename|>server/log.test.js<|end_filename|>
require('./log');

test('stub', () => {});


<|start_filename|>ui/scripts/css.js<|end_filename|>
const fs = require('fs');
const { transform } = require('@multiprocess/cssplus');

const input = fs.readFileSync(process.argv[2]).toString();
fs.writeFileSync(process.argv[3], transform(input));


<|start_filename|>shared/object.test.js<|end_filename|>
const {
  deepEquals,
  mergeDeep,
  getPath,
  setPath,
  validate,
} = require('./object');

test('getPath gets the path in the object', () => {
  const obj = { a: { 1: { b: '12' } } };
  expect(getPath(obj, '')).toStrictEqual(obj);
  expect(getPath(obj, 'a.1.b')).toBe('12');
  expect(getPath(obj, 'a.12.c')).toBe(undefined);
  expect(getPath(obj, 'a.1.c')).toBe(undefined);
});

test('validate rejects missing fields', () => {
  const mock = jest.fn();
  const obj = { a: { 1: { b: '12' } } };
  validate(obj, ['a.1.b'], mock);
  expect(mock.mock.calls.length).toBe(0);

  mock.mockReset();

  validate(obj, ['a.1.b', 'a.2'], mock);
  expect(mock.mock.calls.length).toBe(1);
  expect(mock.mock.calls[0][0]).toBe('a.2');

  mock.mockReset();

  validate(obj, ['a?.1.b', 'a.2?.b', 'a?.3'], mock);
  expect(mock.mock.calls.length).toBe(1);
  expect(mock.mock.calls[0][0]).toBe('a.3');
});

test('mergeDeep', () => {
  expect(
    mergeDeep(
      { a: 1, c: { b: 3 }, e: { f: 9 } },
      { d: 12, c: { g: 22 }, e: { f: 10 } }
    )
  ).toStrictEqual({
    a: 1,
    d: 12,
    c: { b: 3, g: 22 },
    e: { f: 10 },
  });
});

test('deepEquals', () => {
  expect(deepEquals({}, {})).toBe(true);
  expect(deepEquals(1, {})).toBe(false);
  expect(deepEquals({ a: 2, b: { c: 3 } }, { a: 2, b: { c: 3 } })).toBe(true);
  expect(deepEquals({ a: 2, b: { c: 3 } }, { a: 2, b: { c: 4 } })).toBe(false);
});

test('setPath', () => {
  const obj = {
    ns: [{ a: 1 }, { b: 2 }],
  };
  setPath(obj, 'ns.1.b', 3);
  expect(obj).toStrictEqual({
    ns: [{ a: 1 }, { b: 3 }],
  });
});


<|start_filename|>shared/array.test.js<|end_filename|>
const { chunk } = require('./array');

test('chunks an array', () => {
  expect(chunk([1], 0)).toStrictEqual([[1]]);
  expect(chunk([], 1)).toStrictEqual([]);
  expect(chunk([1, 2, 3, 4], 2)).toStrictEqual([
    [1, 2],
    [3, 4],
  ]);
});


<|start_filename|>server/project.test.js<|end_filename|>
const { getProjectHandlers } = require('./project');
const { ProjectState } = require('../shared/state');

test('getProjects', async () => {
  const app = {
    config: {
      database: {
        address: 'localhost:5432',
        username: '',
        password: '',
        database: '',
      },
    },
    dbpool: {},
  };

  let done = false;
  app.dbpool.connect = () => {
    return {
      release() {
        done = true;
      },
      query(q) {
        expect(q).toBe(
          'SELECT project_name, project_created_at FROM projects;'
        );
        return {
          rows: [
            { project_name: 'x', project_created_at: '2021' },
            { project_name: 'y', project_created_at: '2020' },
          ],
        };
      },
    };
  };

  const handlers = getProjectHandlers(app.dbpool);
  const handler = handlers.find((h) => h.resource === 'getProjects');

  const projects = await handler.handler();
  expect(projects).toStrictEqual([
    { name: 'x', createdAt: '2021' },
    { name: 'y', createdAt: '2020' },
  ]);

  expect(done).toBe(true);
});

test('getProject', async () => {
  const app = {
    config: {
      database: {
        address: 'localhost:5432',
        username: '',
        password: '',
        database: '',
      },
    },
    dbpool: {},
  };

  let done = false;
  app.dbpool.connect = () => {
    return {
      release() {
        done = true;
      },
      query(q, [name]) {
        expect(q).toBe(
          'SELECT project_value FROM projects WHERE project_name = $1;'
        );
        expect(name).toBe('this project id');
        const project_value = new ProjectState();
        project_value.projectName = name;
        return { rows: [{ project_value }] };
      },
    };
  };

  const handlers = getProjectHandlers(app.dbpool);
  const handler = handlers.find((h) => h.resource === 'getProject');

  const project = await handler.handler(
    null,
    { projectId: 'this project id' },
    null,
    true
  );
  expect(project.projectName).toStrictEqual('this project id');

  expect(done).toBe(true);
});

test('makeProject', async () => {
  const app = {
    config: {
      database: {
        address: 'localhost:5432',
        username: '',
        password: '',
        database: '',
      },
    },
    dbpool: {},
  };

  let done = false;
  app.dbpool.connect = () => {
    return {
      release() {
        done = true;
      },
      query(q, [projectId, projectState]) {
        expect(q).toBe(
          'INSERT INTO projects (project_name, project_value) VALUES ($1, $2)'
        );
        expect(projectId).toBe('my great project');
        return { rows: [] };
      },
    };
  };

  const handlers = getProjectHandlers(app.dbpool);
  const handler = handlers.find((h) => h.resource === 'makeProject');
  await handler.handler(null, { projectId: 'my great project' });

  expect(done).toBe(true);
});


<|start_filename|>shared/languages/ruby.json<|end_filename|>
{
  "defaultPath": "ruby",
  "id": "ruby",
  "name": "Ruby",
  "preamble": "\ndef DM_getPanel(i)\n  require 'json'\n  JSON.parse(File.read('$$RESULTS_FILE$$' + JSON.parse('$$JSON_ID_MAP$$')[i.to_s]))\nend\n\ndef DM_setPanel(v)\n  require 'json'\n  File.write('$$PANEL_RESULTS_FILE$$', v.to_json)\nend\n\ndef DM_getPanelFile(i)\n  require 'json'\n  '$$RESULTS_FILE$$' + JSON.parse('$$JSON_ID_MAP$$')[i.to_s]\nend\n"
}
