Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(logging): replace jest with vitest #5765

Merged
merged 4 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libs/logging/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
build
coverage
jest.config.js
vitest.config.ts
8 changes: 0 additions & 8 deletions libs/logging/jest.config.js

This file was deleted.

10 changes: 3 additions & 7 deletions libs/logging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"lint": "pnpm type-check && eslint .",
"lint:fix": "pnpm type-check && eslint . --fix",
"test": "is-ci test:ci test:watch",
"test:watch": "TZ=UTC jest --watch",
"test:coverage": "TZ=UTC jest --coverage",
"test:ci": "pnpm build && pnpm test:coverage --reporters=default --reporters=jest-junit --maxWorkers=6 && pnpm build:generate-typescript-types --check && pnpm build:generate-rust-types --check",
"test:watch": "TZ=UTC vitest",
"test:coverage": "TZ=UTC vitest --coverage",
"test:ci": "pnpm build && TZ=UTC vitest run --coverage && pnpm build:generate-typescript-types --check && pnpm build:generate-rust-types --check",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a good time to switch to America/Anchorage timezone?

"pre-commit": "lint-staged"
},
"dependencies": {
Expand All @@ -51,12 +51,8 @@
"eslint-plugin-vx": "workspace:*",
"fast-check": "2.23.2",
"is-ci-cli": "2.2.0",
"jest": "^29.6.2",
"jest-junit": "^16.0.0",
"jest-watch-typeahead": "^2.2.2",
"lint-staged": "11.0.0",
"sort-package-json": "^1.50.0",
"ts-jest": "29.1.1",
"vitest": "^2.1.8"
},
"packageManager": "[email protected]"
Expand Down
1 change: 0 additions & 1 deletion libs/logging/scripts/generate_types_from_toml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ function formatGetDetailsForEventId(config: ParsedConfig): string {
}

output += `
/* istanbul ignore next - compile time check for completeness */
default:
throwIllegalValue(eventId);
}
Expand Down
17 changes: 9 additions & 8 deletions libs/logging/src/base_logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/* eslint-disable no-console */
import { expect, test, vi } from 'vitest';
import { mockKiosk } from '@votingworks/test-utils';
import { LogEventId } from './log_event_ids';
import { LogEventType } from './base_types/log_event_types';
import { CLIENT_SIDE_LOG_SOURCES, LogSource } from './base_types/log_source';
import { BaseLogger } from './base_logger';
import { DEVICE_TYPES_FOR_APP, LogDispositionStandardTypes } from './types';

jest.useFakeTimers().setSystemTime(new Date('2020-07-24T00:00:00.000Z'));
vi.useFakeTimers().setSystemTime(new Date('2020-07-24T00:00:00.000Z'));

test('logger logs server logs as expected', async () => {
console.log = jest.fn();
console.log = vi.fn();
const logger = new BaseLogger(LogSource.System);
await logger.log(LogEventId.MachineBootInit, 'system', {
message: 'I come back stronger than a 90s trend',
Expand All @@ -30,8 +31,8 @@ test('logger logs server logs as expected', async () => {
});

test('logger logs client logs as expected through kiosk browser with overridden message', async () => {
console.log = jest.fn();
const kiosk = mockKiosk();
console.log = vi.fn();
const kiosk = mockKiosk(vi.fn);
const logger = new BaseLogger(LogSource.VxAdminFrontend, kiosk);
await logger.log(LogEventId.ElectionConfigured, 'election_manager', {
message: 'On my tallest tiptoes',
Expand All @@ -55,8 +56,8 @@ test('logger logs client logs as expected through kiosk browser with overridden
});

test('defaults to default message when defined and no disposition', async () => {
console.log = jest.fn();
const kiosk = mockKiosk();
console.log = vi.fn();
const kiosk = mockKiosk(vi.fn);
const logger = new BaseLogger(LogSource.VxAdminFrontend, kiosk);
await logger.log(LogEventId.ElectionUnconfigured, 'election_manager');
expect(kiosk.log).toHaveBeenCalledTimes(1);
Expand All @@ -75,7 +76,7 @@ test('defaults to default message when defined and no disposition', async () =>
});

test('logs unknown disposition as expected', async () => {
console.log = jest.fn();
console.log = vi.fn();
const logger = new BaseLogger(LogSource.System);
await logger.log(LogEventId.MachineBootComplete, 'system', {
message: 'threw out our cloaks and our daggers now',
Expand All @@ -100,7 +101,7 @@ test('logs unknown disposition as expected', async () => {
});

test('logging from a client side app without sending window.kiosk does NOT log to console', async () => {
console.log = jest.fn();
console.log = vi.fn();
const logger = new BaseLogger(LogSource.VxAdminFrontend);
await logger.log(LogEventId.AuthLogin, 'election_manager');
expect(console.log).not.toHaveBeenCalled();
Expand Down
2 changes: 1 addition & 1 deletion libs/logging/src/base_logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class BaseLogger {
};
// If the caller is passing in a debug instance, and we are not in production log to the debugger rather than through the normal logging pipeline.
// This is to make logs more manageable in development, so a developer can toggle what logs to view with the normal debug namespaces.
/* istanbul ignore next - figure out how to test this */
/* istanbul ignore next - figure out how to test this @preserve */
if (outerDebug && process.env.NODE_ENV !== 'production') {
outerDebug(logLine);
return;
Expand Down
6 changes: 6 additions & 0 deletions libs/logging/src/base_types/log_event_types.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { expect, test } from 'vitest';
import { getDocumentationForEventType, LogEventType } from './log_event_types';

test('getDocumentationForEventType implemented for all log event types properly', () => {
Expand All @@ -6,3 +7,8 @@ test('getDocumentationForEventType implemented for all log event types properly'
expect(documentation.eventType).toEqual(eventType);
}
});

test('getDocumentationForEventType rejects invalid event types', () => {
// @ts-expect-error - invalid type
expect(() => getDocumentationForEventType('invalid')).toThrow();
});
1 change: 0 additions & 1 deletion libs/logging/src/base_types/log_event_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export function getDocumentationForEventType(
return ApplicationStatusEventDocumentation;
case LogEventType.ApplicationAction:
return ApplicationActionEventDocumentation;
/* istanbul ignore next - compile time check for completeness */
default:
throwIllegalValue(eventType);
}
Expand Down
17 changes: 10 additions & 7 deletions libs/logging/src/export.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { describe, expect, test, vi } from 'vitest';
import { assert, iter } from '@votingworks/basics';
import { EventLogging, safeParseJson } from '@votingworks/types';
import { createReadStream } from 'node:fs';
import { join } from 'node:path';
import { LogEventId, LogEventType, LogLine, LogSource, mockLogger } from '.';
import { buildCdfLog, filterErrorLogs } from './export';

jest.useFakeTimers().setSystemTime(new Date('2020-07-24T00:00:00.000Z'));
vi.useFakeTimers().setSystemTime(new Date('2020-07-24T00:00:00.000Z'));

describe('filterErrorLogs', () => {
test('converts basic log as expected', async () => {
Expand Down Expand Up @@ -33,7 +34,7 @@ describe('filterErrorLogs', () => {

describe('buildCdfLog', () => {
test('builds device and election info properly', async () => {
const logger = mockLogger({ source: LogSource.VxAdminFrontend });
const logger = mockLogger({ source: LogSource.VxAdminFrontend, fn: vi.fn });
const cdfLogContent = buildCdfLog(
logger,
iter(['']).async(),
Expand Down Expand Up @@ -64,8 +65,9 @@ describe('buildCdfLog', () => {
const logger = mockLogger({
source: LogSource.VxAdminFrontend,
role: 'election_manager',
fn: vi.fn,
});
const logSpy = jest.spyOn(logger, 'log').mockResolvedValue();
const logSpy = vi.spyOn(logger, 'log').mockResolvedValue();
const cdfLogContent = buildCdfLog(
logger,
iter([
Expand Down Expand Up @@ -108,7 +110,7 @@ describe('buildCdfLog', () => {
});

test('log with unspecified disposition as expected', async () => {
const logger = mockLogger({ source: LogSource.VxAdminFrontend });
const logger = mockLogger({ source: LogSource.VxAdminFrontend, fn: vi.fn });
const cdfLogContent = buildCdfLog(
logger,
iter([
Expand All @@ -134,7 +136,7 @@ describe('buildCdfLog', () => {
});

test('converts log with custom disposition and extra details as expected', async () => {
const logger = mockLogger({ source: LogSource.VxAdminFrontend });
const logger = mockLogger({ source: LogSource.VxAdminFrontend, fn: vi.fn });
const cdfLogContent = buildCdfLog(
logger,
iter([
Expand Down Expand Up @@ -172,8 +174,9 @@ describe('buildCdfLog', () => {
const logger = mockLogger({
source: LogSource.VxAdminFrontend,
role: 'election_manager',
fn: vi.fn,
});
const logSpy = jest.spyOn(logger, 'log').mockResolvedValue();
const logSpy = vi.spyOn(logger, 'log').mockResolvedValue();
const missingTimeLogLine: LogLine = {
source: LogSource.System,
eventId: LogEventId.DeviceAttached,
Expand Down Expand Up @@ -239,7 +242,7 @@ describe('buildCdfLog', () => {
const logFile = createReadStream(
join(__dirname, '../fixtures/samplelog.log')
);
const logger = mockLogger({ source: LogSource.VxAdminFrontend });
const logger = mockLogger({ source: LogSource.VxAdminFrontend, fn: vi.fn });
const cdfLogContent = buildCdfLog(logger, logFile, '1234', 'codeversion');
const cdfLogResult = safeParseJson(
await iter(cdfLogContent).toString(),
Expand Down
3 changes: 3 additions & 0 deletions libs/logging/src/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { expect, test } from 'vitest';
import { getLogEventIdForPollsTransition } from './helpers';
import { LogEventId } from './log_event_ids';

Expand All @@ -14,4 +15,6 @@ test('getLogEventIdForPollsTransition', () => {
expect(getLogEventIdForPollsTransition('close_polls')).toEqual(
LogEventId.PollsClosed
);
// @ts-expect-error - invalid value passed to function
expect(() => getLogEventIdForPollsTransition('invalid')).toThrow();
});
1 change: 0 additions & 1 deletion libs/logging/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export function getLogEventIdForPollsTransition(
return LogEventId.VotingResumed;
case 'close_polls':
return LogEventId.PollsClosed;
/* istanbul ignore next */
default:
throwIllegalValue(transitionType);
}
Expand Down
2 changes: 1 addition & 1 deletion libs/logging/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* istanbul ignore file */
/* istanbul ignore file - @preserve */
export * from './base_types';
export * from './export';
export * from './helpers';
Expand Down
3 changes: 2 additions & 1 deletion libs/logging/src/log_documentation.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, expect, test, vi } from 'vitest';
import { EventLogging, safeParseJson } from '@votingworks/types';
import { assert } from '@votingworks/basics';
import * as fs from 'node:fs';
Expand All @@ -8,7 +9,7 @@ import {
} from './log_documentation';
import { AppName } from './base_types/log_source';

jest.useFakeTimers().setSystemTime(new Date('2020-07-24T00:00:00.000Z'));
vi.useFakeTimers().setSystemTime(new Date('2020-07-24T00:00:00.000Z'));

describe('test cdf documentation generation', () => {
test('builds expected documentation for VxAdminFrontend', () => {
Expand Down
6 changes: 6 additions & 0 deletions libs/logging/src/log_event_ids.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { expect, test } from 'vitest';
import { getDetailsForEventId, LogEventId } from './log_event_ids';

test('getDetailsForEventId implemented for all events properly', () => {
Expand All @@ -7,6 +8,11 @@ test('getDetailsForEventId implemented for all events properly', () => {
}
});

test('getDefaultsForEventId rejects invalid event IDs', () => {
// @ts-expect-error - invalid value
expect(() => getDetailsForEventId('invalid')).toThrow();
});

test('all event Ids are unique', () => {
const allEventIds = Object.values(LogEventId);
for (const eventId of allEventIds) {
Expand Down
1 change: 0 additions & 1 deletion libs/logging/src/log_event_ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,6 @@ export function getDetailsForEventId(eventId: LogEventId): LogDetails {
return SignedHashValidationInit;
case LogEventId.SignedHashValidationComplete:
return SignedHashValidationComplete;
/* istanbul ignore next - compile time check for completeness */
default:
throwIllegalValue(eventId);
}
Expand Down
13 changes: 7 additions & 6 deletions libs/logging/src/logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-console */
import { expect, test, vi } from 'vitest';
import {
BaseLogger,
LogDispositionStandardTypes,
Expand All @@ -9,8 +10,8 @@ import {
} from '.';

test('logger can log with passed user role', async () => {
jest.spyOn(console, 'log').mockReturnValue();
const getUserRole = jest.fn();
vi.spyOn(console, 'log').mockReturnValue();
const getUserRole = vi.fn();

const logger = new Logger(LogSource.VxMarkBackend, getUserRole);
getUserRole.mockResolvedValue('election_manager');
Expand Down Expand Up @@ -43,9 +44,9 @@ test('logger can log with passed user role', async () => {
});

test('Logger.from', async () => {
jest.spyOn(console, 'log').mockReturnValue();
vi.spyOn(console, 'log').mockReturnValue();
const baseLogger = new BaseLogger(LogSource.VxCentralScanService);
const logSpy = jest.spyOn(baseLogger, 'log');
const logSpy = vi.spyOn(baseLogger, 'log');
const logger = Logger.from(baseLogger, () => Promise.resolve('unknown'));
await logger.logAsCurrentRole(LogEventId.FileSaved);
expect(console.log).toHaveBeenCalledWith(
Expand All @@ -61,9 +62,9 @@ test('Logger.from', async () => {
});

test('can provide fallback user', async () => {
jest.spyOn(console, 'log').mockReturnValue();
vi.spyOn(console, 'log').mockReturnValue();
const baseLogger = new BaseLogger(LogSource.VxCentralScanService);
const logSpy = jest.spyOn(baseLogger, 'log');
const logSpy = vi.spyOn(baseLogger, 'log');
const logger = Logger.from(baseLogger, () => Promise.resolve('unknown'));
await logger.logAsCurrentRole(
LogEventId.FileSaved,
Expand Down
10 changes: 6 additions & 4 deletions libs/logging/src/test_utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { expect, test, vi } from 'vitest';
import { typedAs } from '@votingworks/basics';
import { LogEventType, LogLine, LogSource } from '.';
import { LogEventId } from './log_event_ids';
import { mockBaseLogger, mockLogger } from './test_utils';

test('mockBaseLogger returns a logger with a spy on logger.log', async () => {
const logger = mockBaseLogger();
const logger = mockBaseLogger({ fn: vi.fn });
await logger.log(LogEventId.MachineBootInit, 'system');
expect(logger.log).toHaveBeenCalledWith(LogEventId.MachineBootInit, 'system');
});

test('mockLogger returns a logger that can print debug logs', async () => {
const logger = mockLogger({ source: LogSource.System });
const debug = jest.fn();
const logger = mockLogger({ source: LogSource.System, fn: vi.fn });
const debug = vi.fn();
await logger.log(LogEventId.MachineBootInit, 'system', undefined, debug);
expect(debug).toHaveBeenCalledWith(
typedAs<LogLine>({
Expand All @@ -29,6 +30,7 @@ test('mockLogger', async () => {
const logger = mockLogger({
source: LogSource.VxAdminService,
role: 'election_manager',
fn: vi.fn,
});

await logger.logAsCurrentRole(LogEventId.MachineBootInit);
Expand Down Expand Up @@ -61,7 +63,7 @@ test('mockLogger', async () => {
});

test('mockLogger with defaults', async () => {
const logger = mockLogger();
const logger = mockLogger({ fn: vi.fn });
await logger.logAsCurrentRole(LogEventId.MachineBootInit);
expect(logger.logAsCurrentRole).toHaveBeenCalledWith(
LogEventId.MachineBootInit
Expand Down
Loading