(core) updates from grist-core

This commit is contained in:
Paul Fitzpatrick 2023-03-06 08:21:09 -05:00
commit 055522d374
16 changed files with 381 additions and 39 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
github: gristlabs

View File

@ -10,24 +10,35 @@ on:
workflow_dispatch:
jobs:
build:
build_and_test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.9]
node-version: [14.x]
tests:
- ':lint:python:client:common:smoke:'
- ':server-1-of-2:'
- ':server-2-of-2:'
- ':nbrowser-1-of-5:'
- ':nbrowser-2-of-5:'
- ':nbrowser-3-of-5:'
- ':nbrowser-4-of-5:'
- ':nbrowser-5-of-5:'
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install Python packages
run: |
@ -38,9 +49,11 @@ jobs:
run: yarn install
- name: Run eslint
if: contains(matrix.tests, ':lint:')
run: yarn run lint:ci
- name: Make sure bucket is versioned
if: contains(matrix.tests, ':server-')
env:
AWS_ACCESS_KEY_ID: administrator
AWS_SECRET_ACCESS_KEY: administrator
@ -49,15 +62,27 @@ jobs:
- name: Build Node.js code
run: yarn run build:prod
- name: Run smoke test
if: contains(matrix.tests, ':smoke:')
run: VERBOSE=1 DEBUG=1 MOCHA_WEBDRIVER_HEADLESS=1 yarn run test:smoke
- name: Run python tests
if: contains(matrix.tests, ':python:')
run: yarn run test:python
- name: Run client tests
if: contains(matrix.tests, ':client:')
run: yarn run test:client
- name: Run common tests
if: contains(matrix.tests, ':common:')
run: yarn run test:common
- name: Run server tests with minio and redis
run: MOCHA_WEBDRIVER_HEADLESS=1 yarn run test:server
if: contains(matrix.tests, ':server-')
run: |
export TEST_SPLITS=$(echo $TESTS | sed "s/.*:server-\([^:]*\).*/\1/")
MOCHA_WEBDRIVER_HEADLESS=1 yarn run test:server
env:
GRIST_DOCS_MINIO_ACCESS_KEY: administrator
GRIST_DOCS_MINIO_SECRET_KEY: administrator
@ -68,15 +93,12 @@ jobs:
GRIST_DOCS_MINIO_BUCKET: grist-docs-test
- name: Run main tests without minio and redis
run: MOCHA_WEBDRIVER_HEADLESS=1 yarn run test --exclude '_build/test/server/**/*'
- name: Update candidate branch
if: ${{ github.event_name == 'push' }}
uses: ad-m/github-push-action@8407731efefc0d8f72af254c74276b7a90be36e1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: latest_candidate
force: true
if: contains(matrix.tests, ':nbrowser-')
run: |
export TEST_SPLITS=$(echo $TESTS | sed "s/.*:nbrowser-\([^:]*\).*/\1/")
MOCHA_WEBDRIVER_HEADLESS=1 yarn run test:nbrowser
env:
TESTS: ${{ matrix.tests }}
services:
# https://github.com/bitnami/bitnami-docker-minio/issues/16
@ -103,3 +125,18 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
candidate:
needs: build_and_test
if: ${{ success() && github.event_name == 'push' }}
runs-on: ubuntu-latest
steps:
- name: Fetch new candidate branch
uses: actions/checkout@v3
- name: Update candidate branch
uses: ad-m/github-push-action@8407731efefc0d8f72af254c74276b7a90be36e1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: latest_candidate
force: true

View File

@ -198,7 +198,7 @@ export class VisibleFieldsConfig extends Disposable {
});
return [
cssHeader(
cssFieldListHeader(dom.text((use) => `Visible ${use(this._fieldLabel)}`)),
cssFieldListHeader(dom.text((use) => t("Visible {{label}}", {label: use(this._fieldLabel)}))),
dom.maybe(
(use) => Boolean(use(use(this._section.viewFields).getObservable()).length),
() => (
@ -215,7 +215,7 @@ export class VisibleFieldsConfig extends Disposable {
dom.maybe(this._showVisibleBatchButtons, () =>
cssRow(
primaryButton(
dom.text((use) => `Hide ${use(this._fieldLabel)}`),
dom.text((use) => t("Hide {{label}}", {label: use(this._fieldLabel)})),
dom.on('click', () => this._removeSelectedFields()),
),
basicButton(
@ -234,7 +234,7 @@ export class VisibleFieldsConfig extends Disposable {
testId('collapse-hidden'),
),
// TODO: show `hidden column` only when some fields are hidden
cssFieldListHeader(dom.text((use) => `Hidden ${use(this._fieldLabel)}`)),
cssFieldListHeader(dom.text((use) => t("Hidden {{label}}", {label: use(this._fieldLabel)}))),
dom.maybe(
(use) => Boolean(use(this._hiddenFields.getObservable()).length && !use(this._collapseHiddenFields)),
() => (
@ -257,7 +257,7 @@ export class VisibleFieldsConfig extends Disposable {
dom.maybe(this._showHiddenBatchButtons, () =>
cssRow(
primaryButton(
dom.text((use) => `Show ${use(this._fieldLabel)}`),
dom.text((use) => t("Show {{label}}", {label: use(this._fieldLabel)})),
dom.on('click', () => this._addSelectedFields()),
),
basicButton(

View File

@ -150,7 +150,7 @@ export function select<T>(obs: Observable<T>, optionArray: MaybeObsArray<IOption
return weasel.select(obs, optionArray, selectOptions, (op) =>
cssOptionRow(
op.icon ? cssOptionRowIcon(op.icon) : null,
cssOptionLabel(op.label),
cssOptionLabel(t(op.label)),
renderOptionArgs ? renderOptionArgs(op) : null,
testId('select-row')
)

View File

@ -1,6 +1,6 @@
{
"name": "grist-core",
"version": "1.0.7",
"version": "1.0.8",
"license": "Apache-2.0",
"description": "Grist is the evolution of spreadsheets",
"homepage": "https://github.com/gristlabs/grist-core",
@ -13,10 +13,10 @@
"build:prod": "buildtools/build.sh",
"start:prod": "sandbox/run.sh",
"test": "GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} --slow 8000 ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} '_build/test/common/*.js' '_build/test/client/*.js' '_build/test/nbrowser/*.js' '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:nbrowser": "GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} --slow 8000 '_build/test/nbrowser/**/*.js'",
"test:nbrowser": "TEST_SUITE=nbrowser TEST_SUITE_FOR_TIMINGS=nbrowser TIMINGS_FILE=test/timings/nbrowser.txt GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} --slow 8000 -R test/xunit-file '_build/test/nbrowser/**/*.js'",
"test:client": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/client/**/*.js'",
"test:common": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/common/**/*.js'",
"test:server": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:server": "TEST_SUITE=server TEST_SUITE_FOR_TIMINGS=server TIMINGS_FILE=test/timings/server.txt GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} -R test/xunit-file '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'",
"test:smoke": "NODE_PATH=_build:_build/stubs:_build/ext mocha _build/test/nbrowser/Smoke.js",
"test:docker": "./test/test_under_docker.sh",
"test:python": "sandbox_venv3/bin/python sandbox/grist/runtests.py ${GREP_TESTS:+discover -p \"test*${GREP_TESTS}*.py\"}",

View File

@ -744,7 +744,11 @@
"Cannot drop items into Hidden Fields": "Elemente können nicht in ausgeblendeten Feldern abgelegt werden",
"Clear": "Klären",
"Hidden Fields cannot be reordered": "Ausgeblendete Felder können nicht neu sortiert werden",
"Select All": "Alle auswählen"
"Select All": "Alle auswählen",
"Hide {{label}}": "{{label}} ausblenden",
"Hidden {{label}}": "{{label}} Versteckt",
"Show {{label}}": "{{label}} anzeigen",
"Visible {{label}}": "Sichtbar {{label}}"
},
"WelcomeQuestions": {
"Education": "Bildung",
@ -803,7 +807,19 @@
"menus": {
"* Workspaces are available on team plans. ": "* Arbeitsbereiche sind in Teamplänen verfügbar. ",
"Select fields": "Felder auswählen",
"Upgrade now": "Jetzt aktualisieren"
"Upgrade now": "Jetzt aktualisieren",
"Numeric": "Numerisch",
"DateTime": "DatumUhrzeit",
"Choice List": "Auswahlliste",
"Choice": "Auswahl",
"Reference": "Referenz",
"Reference List": "Referenzliste",
"Attachment": "Anhang",
"Any": "Jegliche",
"Text": "Text",
"Integer": "Ganze Zahl",
"Toggle": "Umschalten",
"Date": "Datum"
},
"modals": {
"Cancel": "Abbrechen",

View File

@ -688,7 +688,11 @@
"Cannot drop items into Hidden Fields": "Cannot drop items into Hidden Fields",
"Clear": "Clear",
"Hidden Fields cannot be reordered": "Hidden Fields cannot be reordered",
"Select All": "Select All"
"Select All": "Select All",
"Visible {{label}}": "Visible {{label}}",
"Hide {{label}}": "Hide {{label}}",
"Hidden {{label}}": "Hidden {{label}}",
"Show {{label}}": "Show {{label}}"
},
"WelcomeQuestions": {
"Education": "Education",
@ -747,7 +751,19 @@
"menus": {
"* Workspaces are available on team plans. ": "* Workspaces are available on team plans. ",
"Select fields": "Select fields",
"Upgrade now": "Upgrade now"
"Upgrade now": "Upgrade now",
"Any": "Any",
"Numeric": "Numeric",
"Text": "Text",
"Integer": "Integer",
"Toggle": "Toggle",
"Date": "Date",
"DateTime": "DateTime",
"Choice": "Choice",
"Choice List": "Choice List",
"Reference": "Reference",
"Reference List": "Reference List",
"Attachment": "Attachment"
},
"modals": {
"Cancel": "Cancel",

View File

@ -601,7 +601,11 @@
"Cannot drop items into Hidden Fields": "No se pueden colocar elementos en campos ocultos",
"Clear": "Limpiar",
"Hidden Fields cannot be reordered": "Los campos ocultos no pueden ser reordenados",
"Select All": "Seleccionar todo"
"Select All": "Seleccionar todo",
"Hide {{label}}": "Ocultar {{label}}",
"Hidden {{label}}": "{{label}} oculta",
"Show {{label}}": "Mostrar {{label}}",
"Visible {{label}}": "{{label}} visible"
},
"WelcomeQuestions": {
"Education": "Educación",
@ -808,7 +812,19 @@
"menus": {
"* Workspaces are available on team plans. ": "* Los espacios de trabajo están disponibles en los planes de equipo. ",
"Select fields": "Seleccionar campos",
"Upgrade now": "Actualizar ahora"
"Upgrade now": "Actualizar ahora",
"Numeric": "Numérico",
"Text": "Texto",
"Integer": "Entero",
"Date": "Fecha",
"DateTime": "Fecha y hora",
"Choice": "Elección",
"Choice List": "Lista de opciones",
"Reference": "Referencia",
"Reference List": "Lista de referencia",
"Attachment": "Adjunto",
"Any": "Cualquiera",
"Toggle": "Cambiar"
},
"modals": {
"Cancel": "Cancelar",

View File

@ -653,7 +653,8 @@
"Set formula": "Imposta formula",
"Set trigger formula": "Imposta formula trigger",
"TRIGGER FORMULA": "FORMULA TRIGGER",
"Make into data column": "Trasforma in una colonna di dati"
"Make into data column": "Trasforma in una colonna di dati",
"DESCRIPTION": "DESCRIZIONE"
},
"FieldMenus": {
"Save as common settings": "Salva come impostazioni comuni",
@ -832,7 +833,11 @@
"Cannot drop items into Hidden Fields": "Impossibile collocare elementi in campi nascosti",
"Clear": "Svuota",
"Hidden Fields cannot be reordered": "Impossibile riordinare i campi nascosti",
"Select All": "Seleziona tutto"
"Select All": "Seleziona tutto",
"Hidden {{label}}": "Nascosta {{label}}",
"Hide {{label}}": "Nascondi {{label}}",
"Visible {{label}}": "Visibile {{label}}",
"Show {{label}}": "Mostra {{label}}"
},
"WidgetTitle": {
"Cancel": "Annulla",
@ -853,7 +858,19 @@
"menus": {
"* Workspaces are available on team plans. ": "*Gli spazi di lavoro sono disponibili nel piano per i team. ",
"Select fields": "Seleziona campi",
"Upgrade now": "Aggiorna ora"
"Upgrade now": "Aggiorna ora",
"Any": "Qualsiasi",
"Text": "Testo",
"Integer": "Intero",
"Toggle": "Interruttore",
"Date": "Data",
"DateTime": "Data/ora",
"Reference": "Riferimento",
"Reference List": "Lista di riferimenti",
"Choice List": "Scelta da lista",
"Attachment": "Allegato",
"Numeric": "Numerico",
"Choice": "Scelta"
},
"modals": {
"Cancel": "Annulla",

View File

@ -344,7 +344,8 @@
"Empty Columns_other": "Puste kolumny",
"Enter formula": "Wprowadź formułę",
"Make into data column": "Zrób z tego kolumnę danych",
"Set trigger formula": "Ustawianie formuły wyzwalacza"
"Set trigger formula": "Ustawianie formuły wyzwalacza",
"DESCRIPTION": "OPIS"
},
"GridOptions": {
"Zebra Stripes": "Paski zebry",
@ -412,6 +413,53 @@
"All Documents": "Wszystkie dokumenty",
"Create Empty Document": "Utwórz pusty dokument",
"Create Workspace": "Utwórz przestrzeń roboczą",
"Access Details": "Szczegóły dostępu"
"Access Details": "Szczegóły dostępu",
"Rename": "Zmień nazwę",
"Trash": "Kosz",
"Workspaces": "Obszary robocze",
"Workspace will be moved to Trash.": "Obszar roboczy zostanie przeniesiony do kosza.",
"Import Document": "Importuj dokument",
"Manage Users": "Zarządzanie użytkownikami"
},
"Importer": {
"Select fields to match on": "Wybierz pola do dopasowania",
"Merge rows that match these fields:": "Scal wiersze, które pasują do tych pól:",
"Update existing records": "Aktualizowanie istniejących rekordów"
},
"MakeCopyMenu": {
"Update": "Aktualizacja",
"Update Original": "Zaktualizuj oryginał",
"Workspace": "Obszar roboczy",
"You do not have write access to the selected workspace": "Nie masz dostępu do zapisu w wybranej przestrzeni roboczej",
"Cancel": "Anuluj",
"As Template": "Jako szablon",
"Include the structure without any of the data.": "Dołącz strukturę bez żadnych danych.",
"Enter document name": "Wprowadź nazwę dokumentu",
"However, it appears to be already identical.": "Wydaje się jednak, że jest już identyczny.",
"It will be overwritten, losing any content not in this document.": "Zostanie on nadpisany, tracąc wszelkie treści nie znajdujące się w tym dokumencie.",
"Name": "Nazwa",
"No destination workspace": "Brak docelowej przestrzeni roboczej",
"Organization": "Organizacja",
"Overwrite": "Nadpisz",
"Original Has Modifications": "Oryginał ma modyfikacje",
"Original Looks Identical": "Oryginał Wygląda identycznie",
"To save your changes, please sign up, then reload this page.": "Aby zapisać zmiany, proszę się zarejestrować, a następnie ponownie załadować tę stronę.",
"Replacing the original requires editing rights on the original document.": "Zastąpienie oryginału wymaga uprawnień do edycji oryginalnego dokumentu.",
"Sign up": "Zarejestruj się",
"The original version of this document will be updated.": "Oryginalna wersja tego dokumentu zostanie zaktualizowana.",
"You do not have write access to this site": "Nie masz dostępu do zapisu na tej stronie",
"Original Looks Unrelated": "Oryginalny wygląd niepowiązany",
"Be careful, the original has changes not in this document. Those changes will be overwritten.": "Uważaj, oryginał ma zmiany, których nie ma w tym dokumencie. Te zmiany zostaną nadpisane."
},
"NotifyUI": {
"Go to your free personal site": "Przejdź do swojej darmowej strony osobistej",
"No notifications": "Brak powiadomień",
"Ask for help": "Zapytaj o pomoc",
"Cannot find personal site, sorry!": "Nie mogę znaleźć osobistej strony, przepraszam!",
"Give feedback": "Przekaż opinię",
"Notifications": "Powiadomienia"
},
"LeftPanelCommon": {
"Help Center": "Centrum pomocy"
}
}

View File

@ -744,7 +744,11 @@
"Cannot drop items into Hidden Fields": "Não é possível lançar itens em Campos Ocultos",
"Clear": "Limpar",
"Hidden Fields cannot be reordered": "Campos ocultos não podem ser reordenados",
"Select All": "Selecionar Todos"
"Select All": "Selecionar Todos",
"Hidden {{label}}": "{{label}} escondido",
"Show {{label}}": "Mostrar {{label}}",
"Visible {{label}}": "{{label}} visível",
"Hide {{label}}": "Ocultar {{label}}"
},
"WelcomeQuestions": {
"Education": "Educação",
@ -803,7 +807,19 @@
"menus": {
"* Workspaces are available on team plans. ": "* As áreas de trabalho estão disponíveis nos planos de equipe. ",
"Select fields": "Selecionar campos",
"Upgrade now": "Atualizar agora"
"Upgrade now": "Atualizar agora",
"Numeric": "Numérico",
"Text": "Texto",
"Integer": "Inteiro",
"Toggle": "Alternar",
"Date": "Data",
"DateTime": "DataHora",
"Choice List": "Lista de opções",
"Reference List": "Lista de Referências",
"Attachment": "Anexo",
"Any": "Qualquer",
"Choice": "Opção",
"Reference": "Referência"
},
"modals": {
"Cancel": "Cancelar",

View File

@ -4,7 +4,7 @@
"Attribute name": "Имя атрибута",
"Add Default Rule": "Добавить правило по умолчанию",
"Add Column Rule": "Добавить правило столбца",
"View As": "Посмотреть как",
"View As": "Смотреть как",
"Seed rules": "Наследуемые правила",
"Add User Attributes": "Добавить атрибуты пользователя",
"Add Table Rules": "Добавить правила таблицы",
@ -798,7 +798,11 @@
"Clear": "Очистить",
"Hidden Fields cannot be reordered": "Скрытые поля не могут быть переупорядочены",
"Cannot drop items into Hidden Fields": "Невозможно поместить элементы в скрытые поля",
"Select All": "Выбрать все"
"Select All": "Выбрать все",
"Hide {{label}}": "Скрыть {{label}}",
"Hidden {{label}}": "Скрытый {{label}}",
"Show {{label}}": "Показать {{label}}",
"Visible {{label}}": "Видимый {{label}}"
},
"WelcomeQuestions": {
"Marketing": "Маркетинг",
@ -826,7 +830,19 @@
"menus": {
"Select fields": "Выберите поля",
"Upgrade now": "Обновитесь сейчас",
"* Workspaces are available on team plans. ": "* Рабочие пространства доступны в командных тарифах. "
"* Workspaces are available on team plans. ": "* Рабочие пространства доступны в командных тарифах. ",
"Any": "Любые",
"Numeric": "Численный",
"Text": "Текст",
"Toggle": "Переключатель",
"Date": "Дата",
"Choice": "Выбор",
"Reference List": "Ссылки списком",
"Choice List": "Выбор списком",
"Attachment": "Вложения",
"DateTime": "Дата и Время",
"Integer": "Целочисленный",
"Reference": "Ссылка"
},
"modals": {
"Cancel": "Отмена",

View File

@ -1,4 +1,5 @@
--require source-map-support/register
test/report-why-tests-hang
test/init-mocha-webdriver
test/split-tests
test/chai-as-promised

121
test/split-tests.js Normal file
View File

@ -0,0 +1,121 @@
/**
* This module handles splitting tests for parallelizing them. This module is imported by any run
* of mocha, due by being listed in test/mocha.opts.
*
* It only does anything if TEST_SPLITS is set, which must have the form "3-of-8".
*
* If TEST_SPLITS is set to M-of-N, it is used to divide up all test suites in this mocha run into
* N groups, and runs the Mth of them. Note that M is 1-based, i.e. in [1..N] range. To have all
* tests run, each of the groups 1-of-N through N-of-N must run on the same total set of tests.
*
* The actual breaking into groups is informed by a timings file, defaulting to
* test/timings-all.txt. This has the format "<top-suite> <file-suite-title> <duration-in-ms>".
* Only those lines whose <top-suite> matches process.env.TEST_SUITE_FOR_TIMINGS will be used.
*
* The timings for test/timings-all.txt are prepared by our test reporter and written during
* Jenkins run as the timings/timings-all.txt artifact. After tests are added or changed, if
* timings may have changed significantly, it's good to update test/timings-all.txt, so that the
* parallel groups can be evened out as much as possible.
*/
/* global before */
const fs = require('fs');
const { assert } = require('chai');
const testSuite = process.env.TEST_SUITE_FOR_TIMINGS || "unset_suite";
const timingsFile = process.env.TIMINGS_FILE || "test/timings-all.txt";
before(function() {
const testSplits = process.env.TEST_SPLITS;
if (!testSplits) {
return;
}
const match = testSplits.match(/^(\d+)-of-(\d+)$/);
if (!match) {
assert.fail(`Invalid test split spec '${testSplits}': use format 'N-of-M'`);
}
const group = Number(match[1]);
const groupCount = Number(match[2]);
if (!(group >= 1 && group <= groupCount)) {
assert.fail(`Invalid test split spec '${testSplits}': index must be in range 1..{groupCount}`);
}
const testParent = this.test.parent;
const timings = getTimings();
const groups = groupSuites(testParent.suites, timings, groupCount);
testParent.suites = groups[group - 1]; // Convert to a 0-based index.
console.log(`Split tests groups; will run group ${group} of ${groupCount}`);
});
/**
* Read timings from timingsFile into a Map mapping file-suite-title to duration.
*/
function getTimings() {
const timings = new Map();
try {
const content = fs.readFileSync(timingsFile, {encoding: 'utf8'})
for (const line of content.split(/\r?\n/)) {
const [bigSuite, fileSuite, duration] = line.split(/\s+/);
if (bigSuite === testSuite && !isNaN(Number(duration))) {
timings.set(fileSuite, Number(duration));
}
}
} catch (e) {
if (e.code === 'ENOENT') {
console.warn(`No timings found in ${timingsFile}; proceeding without timings`);
} else {
throw e;
}
}
return timings;
}
/**
* Splits suites into groups and returns the list of them.
*
* The algorithm to group tests into suites starts goes one by one from longest to shortest,
* adding them to the least filled-up group.
*/
function groupSuites(suites, timings, groupCount) {
// Calculate a fallback value for durations as the average of existing durations.
const totalDuration = Array.from(timings.values()).reduce(((s, dur) => s + dur), 0);
if (!totalDuration) {
console.warn("No timings; assuming all tests are equally long");
}
const fallbackDuration = totalDuration ? totalDuration / timings.size : 1000;
const groups = Array.from(Array(groupCount), () => []);
const groupDurations = groups.map(() => 0);
// Check for duplicate suite titles.
const suitesByTitle = new Map(suites.map(s => [s.title, s]));
for (const suite of suites) {
if (suitesByTitle.get(suite.title) !== suite) {
assert.fail(`Please fix duplicate suite title: ${suite.title}`);
}
}
// Get timing for the given suite, falling back to fallbackDuration.
function getTiming(suite) {
const value = timings.get(suite.title);
return (typeof value !== 'number' || isNaN(value)) ? fallbackDuration : value;
}
// Sort suites by descending duration.
const sortedSuites = suites.slice().sort((a, b) => getTiming(b) - getTiming(a));
for (const suite of sortedSuites) {
// Pick a least-duration group.
const index = groupDurations.indexOf(Math.min(...groupDurations));
groups[index].push(suite);
groupDurations[index] += getTiming(suite);
}
// Sort each group alphabetically by title.
for (const group of groups) {
group.sort((a, b) => a.title < b.title ? -1 : 1);
}
return groups;
}

28
test/timings/nbrowser.txt Normal file
View File

@ -0,0 +1,28 @@
nbrowser ActionLog 14737
nbrowser ChoiceList 33037
nbrowser CustomView 22055
nbrowser CustomWidgets 14958
nbrowser CustomWidgetsConfig 48287
nbrowser DescriptionColumn 4649
nbrowser DuplicateDocument 14042
nbrowser Fork 112089
nbrowser HomeIntro 44706
nbrowser LanguageSettings 25427
nbrowser Localization 10069
nbrowser MultiColumn 455648
nbrowser Pages 24986
nbrowser ReferenceColumns 27590
nbrowser ReferenceList 34333
nbrowser RefTransforms 9072
nbrowser RightPanel 10530
nbrowser RightPanelSelectBy 6255
nbrowser RowMenu 3702
nbrowser saveViewSection 7596
nbrowser SelectBy 5846
nbrowser SelectByRefList 15186
nbrowser SelectByRightPanel 3531
nbrowser SelectBySummary 17516
nbrowser SelectBySummaryRef 5382
nbrowser SelectionSummary 6833
nbrowser Smoke 1800
nbrowser ToggleColumns 6530

7
test/timings/server.txt Normal file
View File

@ -0,0 +1,7 @@
server Comm 9557
server generateInitialDocSql 1304
server Authorizer 2375
server DocApi 94358
server DocApi2 730
server HostedStorageManager 220307
server backupSqliteDatabase 4348