Skip to content

Commit a4ff389

Browse files
committed
[tests] Configure both database servers in one place
PostgreSQL and SQL Server were configured two different ways, and neither in one place: the PostgreSQL URL was written out five times in the harness, and SQL Server read four environment variables. Both now come from `provide` in vitest.config.ts. A project's provide merges over the root's rather than replacing it, so the '-servers' projects keep the databases while overriding their own flag. The harness reads them, and the five repeated URLs collapse to one constant. The documentation examples had their own copies again, eight of them. Rather than have them recite credentials a reader might paste into their own code, they keep spelling out a plain local database, and the doc tests rewrite that pattern to whatever this run is configured against - adding, for SQL Server, the login that PostgreSQL does not need. So the mssql examples now read like the PostgreSQL ones instead of reaching into process.env, and TINYBASE_MSSQL is gone entirely. Checked by pointing the config at ports nothing listens on: both the harness and the documentation examples fail, which is what proves they are reading it rather than a default of their own.
1 parent d906bc8 commit a4ff389

6 files changed

Lines changed: 77 additions & 52 deletions

File tree

‎site/guides/20_releases.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ import {connect} from 'mssql';
7070
import {createStore} from 'tinybase';
7171
import {createMsSqlPersister} from 'tinybase/persisters/persister-mssql';
7272

73-
const msSqlPool = await connect(process.env.TINYBASE_MSSQL);
73+
const msSqlPool = await connect('Server=localhost,1433;Database=tinybase');
7474
const msSqlStore = createStore().setTables({pets: {fido: {species: 'dog'}}});
7575
const msSqlPersister = await createMsSqlPersister(
7676
msSqlStore,

‎src/@types/persisters/persister-mssql/docs.js‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
*
3333
* This module currently supports the JSON serialization mode only.
3434
*
35-
* The examples in this documentation connect with the `TINYBASE_MSSQL`
36-
* environment variable, which should be set to a connection string for a
37-
* scratch database.
35+
* The examples below connect to a local `tinybase` database. A real
36+
* connection string also carries the login, or the authentication type that
37+
* stands in for one on Azure.
3838
* @see Database Persistence guide
3939
* @packageDocumentation
4040
* @module persister-mssql
@@ -69,7 +69,7 @@
6969
* import {createStore} from 'tinybase';
7070
* import {createMsSqlPersister} from 'tinybase/persisters/persister-mssql';
7171
*
72-
* const pool = await connect(process.env.TINYBASE_MSSQL);
72+
* const pool = await connect('Server=localhost,1433;Database=tinybase');
7373
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
7474
* const persister = await createMsSqlPersister(store, pool, 'my_tinybase');
7575
*
@@ -134,7 +134,7 @@
134134
* import {createStore} from 'tinybase';
135135
* import {createMsSqlPersister} from 'tinybase/persisters/persister-mssql';
136136
*
137-
* const pool = await connect(process.env.TINYBASE_MSSQL);
137+
* const pool = await connect('Server=localhost,1433;Database=tinybase');
138138
* const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
139139
* const persister = await createMsSqlPersister(store, pool, 'my_tinybase');
140140
*

‎test/unit/common/other.ts‎

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,23 @@ export const withServers: boolean = isBun
1515
: (vitest as {inject?: (key: 'servers') => boolean}).inject?.('servers') ==
1616
true;
1717

18-
// The local SQL Server these tests expect, given the same treatment as the
19-
// PostgreSQL URL in databases.ts. PostgreSQL can use trust authentication and
20-
// so needs no password; SQL Server cannot, so one is spelled out here. It is
21-
// the password of a throwaway container holding nothing but test data, never
22-
// a real instance:
23-
//
24-
// docker run -d --name tinybase-mssql -p 1433:1433 \
25-
// -e ACCEPT_EULA=Y -e MSSQL_PID=Developer \
26-
// -e MSSQL_SA_PASSWORD='TinyBase!Passw0rd' \
27-
// mcr.microsoft.com/mssql/server:2022-latest
28-
//
29-
// Point any part of it somewhere else with the matching variable.
30-
export const MSSQL_SERVER = process.env.TINYBASE_MSSQL_SERVER ?? 'localhost';
31-
export const MSSQL_PORT = Number(process.env.TINYBASE_MSSQL_PORT ?? 1433);
32-
export const MSSQL_USER = process.env.TINYBASE_MSSQL_USER ?? 'sa';
33-
export const MSSQL_PASSWORD =
34-
process.env.TINYBASE_MSSQL_PASSWORD ?? 'TinyBase!Passw0rd';
35-
export const MSSQL_CONNECTION_STRING =
36-
`Server=${MSSQL_SERVER},${MSSQL_PORT};Database=tinybase;` +
37-
`User Id=${MSSQL_USER};Password=${MSSQL_PASSWORD};` +
18+
// The two database servers, configured once in vitest.config.ts. Bun aliases
19+
// 'vitest' to 'bun:test', which has no inject, but it runs no database variant
20+
// and no server-backed example, so these go unused there.
21+
const injected = (vitest as {inject?: (key: string) => any}).inject;
22+
23+
export const POSTGRES_URL: string = injected?.('postgres');
24+
25+
export const MSSQL_CONFIG: {
26+
server: string;
27+
port: number;
28+
user: string;
29+
password: string;
30+
} = injected?.('mssql');
31+
32+
export const getMsSqlConnectionString = (database: string): string =>
33+
`Server=${MSSQL_CONFIG.server},${MSSQL_CONFIG.port};Database=${database};` +
34+
`User Id=${MSSQL_CONFIG.user};Password=${MSSQL_CONFIG.password};` +
3835
`Encrypt=false;TrustServerCertificate=true`;
3936

4037
export const AsyncFunction = Object.getPrototypeOf(

‎test/unit/documentation.test.ts‎

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ import {AutomergeTestNetworkAdapter as BroadcastChannelNetworkAdapter} from './c
6767
import {getTimeFunctions} from './common/mergeable.ts';
6868
import {
6969
AsyncFunction,
70+
getMsSqlConnectionString,
7071
importBunSqlite,
7172
isBun,
72-
MSSQL_CONNECTION_STRING,
7373
pause,
74+
POSTGRES_URL,
7475
suppressWarnings,
7576
withServers,
7677
} from './common/other.ts';
@@ -333,8 +334,21 @@ const transformSolidJsx = (source: string, loader: 'jsx' | 'tsx'): string =>
333334
{presets: [['solid', {delegateEvents: false}]]},
334335
)?.code ?? '';
335336

337+
// The examples spell out a plain local database, which is what a reader should
338+
// see, so they say nothing about credentials. Point them at whatever this run
339+
// is configured against, which for SQL Server means adding the login that
340+
// PostgreSQL does not need. Bun has no inject and runs none of these.
341+
const replaceDatabaseUrls = (source: string): string =>
342+
POSTGRES_URL == undefined
343+
? source
344+
: source
345+
.replace(/postgres:\/\/localhost:5432/g, POSTGRES_URL)
346+
.replace(/Server=localhost,1433;Database=(\w+)/g, (_, database) =>
347+
getMsSqlConnectionString(database),
348+
);
349+
336350
const prepareRunnableCode = (source: string, replaceImports: boolean): string =>
337-
(replaceImports ? replaceRunnableImports(source) : source)
351+
replaceDatabaseUrls(replaceImports ? replaceRunnableImports(source) : source)
338352
.replace(
339353
/console\.log\((.+?)\.innerHTML\);$/gm,
340354
'_actual.push(getHtml($1));',
@@ -770,11 +784,6 @@ ${body
770784
expect(problem).toBeUndefined();
771785
};
772786

773-
// The mssql examples deliberately read their connection string from the
774-
// environment rather than spelling out credentials a reader might copy. Point
775-
// it at the local instance when nothing else has, so the suite needs no setup.
776-
process.env.TINYBASE_MSSQL ??= MSSQL_CONNECTION_STRING;
777-
778787
describe('Documentation tests', () => {
779788
beforeAll(async () => {
780789
if (isBun) {

‎test/unit/persisters/common/databases.ts‎

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@ import {createSqliteWasmPersister} from 'tinybase/persisters/persister-sqlite-wa
3535
import tmp from 'tmp';
3636
import {afterAll, expect} from 'vitest';
3737
import {
38-
MSSQL_PASSWORD,
39-
MSSQL_PORT,
40-
MSSQL_SERVER,
41-
MSSQL_USER,
38+
MSSQL_CONFIG,
39+
POSTGRES_URL,
4240
importBunSqlite,
4341
isBun,
4442
noop,
@@ -68,7 +66,7 @@ export type SqlClientsAndName = [Sql, ReservedSql, string];
6866
export type PgClientsAndName = [Pool, PoolClient, Mutex, string];
6967
export type MsSqlPoolsAndName = [ConnectionPool, ConnectionPool, Mutex, string];
7068

71-
const PG_ADMIN_URL = 'postgres://localhost:5432/postgres';
69+
const PG_ADMIN_URL = POSTGRES_URL + '/postgres';
7270
const PG_OPTIONS = '-c client_min_messages=warning';
7371

7472
const pgAdmin = async (sql: string) => {
@@ -80,13 +78,9 @@ const pgAdmin = async (sql: string) => {
8078
await adminPool.end();
8179
};
8280

83-
// As with the PostgreSQL URL above, this is the local instance the tests
84-
// expect; see the constants in other.ts for what it is and how to override it.
81+
// Both servers are configured in vitest.config.ts; see `provide` there.
8582
const getMsSqlConfig = (database: string) => ({
86-
server: MSSQL_SERVER,
87-
port: MSSQL_PORT,
88-
user: MSSQL_USER,
89-
password: MSSQL_PASSWORD,
83+
...MSSQL_CONFIG,
9084
database,
9185
pool: {max: 20},
9286
options: {encrypt: false, trustServerCertificate: true},
@@ -464,12 +458,12 @@ export const NODE_POSTGRESQL_VARIANTS: Variants = {
464458
const existingName = sqlClientsAndName?.[2];
465459
const name = existingName ?? 'tinybase_' + getUniqueId();
466460
if (!existingName) {
467-
const adminSql = postgres('postgres://localhost:5432/postgres');
461+
const adminSql = postgres(PG_ADMIN_URL);
468462
await adminSql`CREATE DATABASE ${adminSql(name)}`;
469463
await adminSql.end({timeout: 0.1});
470464
}
471465

472-
const sql = postgres('postgres://localhost:5432/' + name, {
466+
const sql = postgres(POSTGRES_URL + '/' + name, {
473467
connection: {client_min_messages: 'warning'},
474468
});
475469
const cmdSql = await sql.reserve();
@@ -496,7 +490,7 @@ export const NODE_POSTGRESQL_VARIANTS: Variants = {
496490
cmdSql.release();
497491
await sql.end({timeout: 0.1});
498492

499-
const adminSql = postgres('postgres://localhost:5432/postgres', {
493+
const adminSql = postgres(PG_ADMIN_URL, {
500494
connection: {client_min_messages: 'warning'},
501495
});
502496
await adminSql`DROP DATABASE IF EXISTS ${adminSql(name)} WITH (FORCE)`;
@@ -516,7 +510,7 @@ export const NODE_POSTGRESQL_VARIANTS: Variants = {
516510
}
517511

518512
const pool = new Pool({
519-
connectionString: 'postgres://localhost:5432/' + name,
513+
connectionString: POSTGRES_URL + '/' + name,
520514
options: PG_OPTIONS,
521515
max: 20,
522516
});

‎vitest.config.ts‎

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,35 @@ export default defineConfig({
3333
reporter: ['text-summary', 'json-summary', 'html'],
3434
},
3535

36-
// Which half of the database work a project runs. The '-servers' projects
37-
// below override this; everything else leaves those variants and
38-
// documentation examples alone, so the suite needs no database server.
39-
provide: {servers: false},
36+
provide: {
37+
// Which half of the database work a project runs. The '-servers'
38+
// projects below override this; everything else leaves those variants
39+
// and documentation examples alone, so the suite needs no database
40+
// server. A project's provide merges over these, rather than replacing
41+
// them, so the two databases below reach every project.
42+
servers: false,
43+
44+
// The two database servers the suite expects, in the one place they are
45+
// configured. The tests read them from here, and the documentation
46+
// examples - which spell out a plain local database, as a reader should
47+
// see - are rewritten to match before they run.
48+
//
49+
// PostgreSQL uses trust authentication and so needs no password. SQL
50+
// Server cannot, so a password is here; it belongs to a throwaway
51+
// container holding nothing but test data, never a real instance:
52+
//
53+
// docker run -d --name tinybase-mssql -p 1433:1433 \
54+
// -e ACCEPT_EULA=Y -e MSSQL_PID=Developer \
55+
// -e MSSQL_SA_PASSWORD='TinyBase!Passw0rd' \
56+
// mcr.microsoft.com/mssql/server:2022-latest
57+
postgres: 'postgres://localhost:5432',
58+
mssql: {
59+
server: 'localhost',
60+
port: 1433,
61+
user: 'sa',
62+
password: 'TinyBase!Passw0rd',
63+
},
64+
},
4065

4166
onUnhandledError: ({message}) =>
4267
message !== 'Invariant: worker WS endpoint not found',

0 commit comments

Comments
 (0)