2024-03-20 19:32:04 +01:00
|
|
|
import { BadRequestException } from '@nestjs/common';
|
2024-03-20 21:20:38 +01:00
|
|
|
import { defaults } from 'src/cores/system-config.core';
|
2023-07-09 04:43:11 +02:00
|
|
|
import {
|
|
|
|
AudioCodec,
|
2023-10-24 17:05:42 +02:00
|
|
|
CQMode,
|
2024-03-20 19:32:04 +01:00
|
|
|
Colorspace,
|
2024-04-02 06:56:56 +02:00
|
|
|
ImageFormat,
|
2023-12-14 17:55:40 +01:00
|
|
|
LogLevel,
|
2023-07-09 04:43:11 +02:00
|
|
|
SystemConfig,
|
|
|
|
SystemConfigEntity,
|
|
|
|
SystemConfigKey,
|
2023-08-07 22:35:25 +02:00
|
|
|
ToneMapping,
|
2023-08-02 03:56:10 +02:00
|
|
|
TranscodeHWAccel,
|
2023-07-09 04:43:11 +02:00
|
|
|
TranscodePolicy,
|
|
|
|
VideoCodec,
|
2024-03-20 22:02:51 +01:00
|
|
|
} from 'src/entities/system-config.entity';
|
2024-03-22 23:24:02 +01:00
|
|
|
import { IEventRepository, ServerEvent } from 'src/interfaces/event.interface';
|
2024-03-21 12:59:49 +01:00
|
|
|
import { QueueName } from 'src/interfaces/job.interface';
|
|
|
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
|
|
|
import { ISystemConfigRepository } from 'src/interfaces/system-config.interface';
|
2024-03-21 00:07:30 +01:00
|
|
|
import { SystemConfigService } from 'src/services/system-config.service';
|
2024-03-21 04:15:09 +01:00
|
|
|
import { ImmichLogger } from 'src/utils/logger';
|
2024-03-22 23:24:02 +01:00
|
|
|
import { newEventRepositoryMock } from 'test/repositories/event.repository.mock';
|
2024-03-20 19:32:04 +01:00
|
|
|
import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock';
|
2023-01-21 17:11:55 +01:00
|
|
|
|
|
|
|
const updates: SystemConfigEntity[] = [
|
2023-05-22 20:07:43 +02:00
|
|
|
{ key: SystemConfigKey.FFMPEG_CRF, value: 30 },
|
2023-01-21 17:11:55 +01:00
|
|
|
{ key: SystemConfigKey.OAUTH_AUTO_LAUNCH, value: true },
|
2023-10-06 09:01:14 +02:00
|
|
|
{ key: SystemConfigKey.TRASH_DAYS, value: 10 },
|
2024-03-06 06:45:40 +01:00
|
|
|
{ key: SystemConfigKey.USER_DELETE_DELAY, value: 15 },
|
2023-01-21 17:11:55 +01:00
|
|
|
];
|
|
|
|
|
2023-06-01 12:32:51 +02:00
|
|
|
const updatedConfig = Object.freeze<SystemConfig>({
|
|
|
|
job: {
|
|
|
|
[QueueName.BACKGROUND_TASK]: { concurrency: 5 },
|
2023-12-16 17:50:46 +01:00
|
|
|
[QueueName.SMART_SEARCH]: { concurrency: 2 },
|
2023-06-01 12:32:51 +02:00
|
|
|
[QueueName.METADATA_EXTRACTION]: { concurrency: 5 },
|
2024-01-18 06:08:48 +01:00
|
|
|
[QueueName.FACE_DETECTION]: { concurrency: 2 },
|
2023-06-01 12:32:51 +02:00
|
|
|
[QueueName.SEARCH]: { concurrency: 5 },
|
|
|
|
[QueueName.SIDECAR]: { concurrency: 5 },
|
2023-10-11 00:59:13 +02:00
|
|
|
[QueueName.LIBRARY]: { concurrency: 5 },
|
2023-09-25 17:07:21 +02:00
|
|
|
[QueueName.MIGRATION]: { concurrency: 5 },
|
2023-06-01 12:32:51 +02:00
|
|
|
[QueueName.THUMBNAIL_GENERATION]: { concurrency: 5 },
|
|
|
|
[QueueName.VIDEO_CONVERSION]: { concurrency: 1 },
|
|
|
|
},
|
2023-01-21 17:11:55 +01:00
|
|
|
ffmpeg: {
|
2023-05-22 20:07:43 +02:00
|
|
|
crf: 30,
|
|
|
|
threads: 0,
|
2023-01-21 17:11:55 +01:00
|
|
|
preset: 'ultrafast',
|
2023-07-09 04:43:11 +02:00
|
|
|
targetAudioCodec: AudioCodec.AAC,
|
2024-02-21 06:25:30 +01:00
|
|
|
acceptedAudioCodecs: [AudioCodec.AAC, AudioCodec.MP3, AudioCodec.LIBOPUS],
|
2023-04-04 03:42:53 +02:00
|
|
|
targetResolution: '720',
|
2023-07-09 04:43:11 +02:00
|
|
|
targetVideoCodec: VideoCodec.H264,
|
2024-01-26 18:02:56 +01:00
|
|
|
acceptedVideoCodecs: [VideoCodec.H264],
|
2023-05-22 20:07:43 +02:00
|
|
|
maxBitrate: '0',
|
2023-09-03 03:22:42 +02:00
|
|
|
bframes: -1,
|
|
|
|
refs: 0,
|
|
|
|
gopSize: 0,
|
|
|
|
npl: 0,
|
|
|
|
temporalAQ: false,
|
|
|
|
cqMode: CQMode.AUTO,
|
2023-05-22 20:07:43 +02:00
|
|
|
twoPass: false,
|
2024-01-30 02:40:02 +01:00
|
|
|
preferredHwDevice: 'auto',
|
2023-07-09 04:43:11 +02:00
|
|
|
transcode: TranscodePolicy.REQUIRED,
|
2023-08-02 03:56:10 +02:00
|
|
|
accel: TranscodeHWAccel.DISABLED,
|
2023-08-07 22:35:25 +02:00
|
|
|
tonemap: ToneMapping.HABLE,
|
2023-01-21 17:11:55 +01:00
|
|
|
},
|
2023-12-14 17:55:40 +01:00
|
|
|
logging: {
|
|
|
|
enabled: true,
|
|
|
|
level: LogLevel.LOG,
|
|
|
|
},
|
2023-08-25 06:15:03 +02:00
|
|
|
machineLearning: {
|
|
|
|
enabled: true,
|
|
|
|
url: 'http://immich-machine-learning:3003',
|
2023-08-29 15:58:00 +02:00
|
|
|
clip: {
|
|
|
|
enabled: true,
|
2023-10-31 11:02:04 +01:00
|
|
|
modelName: 'ViT-B-32__openai',
|
2023-08-29 15:58:00 +02:00
|
|
|
},
|
|
|
|
facialRecognition: {
|
|
|
|
enabled: true,
|
|
|
|
modelName: 'buffalo_l',
|
|
|
|
minScore: 0.7,
|
2024-03-07 04:20:38 +01:00
|
|
|
maxDistance: 0.5,
|
2024-01-18 06:08:48 +01:00
|
|
|
minFaces: 3,
|
2023-08-29 15:58:00 +02:00
|
|
|
},
|
2023-08-25 06:15:03 +02:00
|
|
|
},
|
2023-09-09 04:51:46 +02:00
|
|
|
map: {
|
|
|
|
enabled: true,
|
2023-11-09 17:10:56 +01:00
|
|
|
lightStyle: '',
|
|
|
|
darkStyle: '',
|
2023-09-09 04:51:46 +02:00
|
|
|
},
|
2023-09-26 09:03:57 +02:00
|
|
|
reverseGeocoding: {
|
|
|
|
enabled: true,
|
|
|
|
},
|
2023-01-21 17:11:55 +01:00
|
|
|
oauth: {
|
|
|
|
autoLaunch: true,
|
|
|
|
autoRegister: true,
|
|
|
|
buttonText: 'Login with OAuth',
|
|
|
|
clientId: '',
|
|
|
|
clientSecret: '',
|
2024-03-02 01:46:07 +01:00
|
|
|
defaultStorageQuota: 0,
|
2023-01-21 17:11:55 +01:00
|
|
|
enabled: false,
|
|
|
|
issuerUrl: '',
|
|
|
|
mobileOverrideEnabled: false,
|
|
|
|
mobileRedirectUri: '',
|
|
|
|
scope: 'openid email profile',
|
2024-02-02 06:27:54 +01:00
|
|
|
signingAlgorithm: 'RS256',
|
2023-07-15 21:50:29 +02:00
|
|
|
storageLabelClaim: 'preferred_username',
|
2024-03-02 01:46:07 +01:00
|
|
|
storageQuotaClaim: 'immich_quota',
|
2023-01-21 17:11:55 +01:00
|
|
|
},
|
|
|
|
passwordLogin: {
|
|
|
|
enabled: true,
|
|
|
|
},
|
2024-01-04 03:54:48 +01:00
|
|
|
server: {
|
|
|
|
externalDomain: '',
|
2024-01-04 06:00:17 +01:00
|
|
|
loginPageMessage: '',
|
2024-01-04 03:54:48 +01:00
|
|
|
},
|
2023-01-21 17:11:55 +01:00
|
|
|
storageTemplate: {
|
2023-12-29 19:41:33 +01:00
|
|
|
enabled: false,
|
|
|
|
hashVerificationEnabled: true,
|
2023-01-21 17:11:55 +01:00
|
|
|
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
|
|
|
},
|
2024-04-02 06:56:56 +02:00
|
|
|
image: {
|
|
|
|
thumbnailFormat: ImageFormat.WEBP,
|
|
|
|
thumbnailSize: 250,
|
|
|
|
previewFormat: ImageFormat.JPEG,
|
|
|
|
previewSize: 1440,
|
2023-09-03 08:21:51 +02:00
|
|
|
quality: 80,
|
|
|
|
colorspace: Colorspace.P3,
|
2023-08-08 16:39:51 +02:00
|
|
|
},
|
2023-10-24 17:05:42 +02:00
|
|
|
newVersionCheck: {
|
|
|
|
enabled: true,
|
|
|
|
},
|
2023-10-06 09:01:14 +02:00
|
|
|
trash: {
|
|
|
|
enabled: true,
|
|
|
|
days: 10,
|
|
|
|
},
|
2023-10-23 20:38:41 +02:00
|
|
|
theme: {
|
|
|
|
customCss: '',
|
|
|
|
},
|
2023-10-31 21:19:12 +01:00
|
|
|
library: {
|
|
|
|
scan: {
|
|
|
|
enabled: true,
|
|
|
|
cronExpression: '0 0 * * *',
|
|
|
|
},
|
2024-01-31 09:15:54 +01:00
|
|
|
watch: {
|
|
|
|
enabled: false,
|
|
|
|
},
|
2023-10-31 21:19:12 +01:00
|
|
|
},
|
2024-03-06 06:45:40 +01:00
|
|
|
user: {
|
|
|
|
deleteDelay: 15,
|
|
|
|
},
|
2023-01-21 17:11:55 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
describe(SystemConfigService.name, () => {
|
|
|
|
let sut: SystemConfigService;
|
|
|
|
let configMock: jest.Mocked<ISystemConfigRepository>;
|
2024-03-22 23:24:02 +01:00
|
|
|
let eventMock: jest.Mocked<IEventRepository>;
|
2024-02-13 02:50:47 +01:00
|
|
|
let smartInfoMock: jest.Mocked<ISearchRepository>;
|
2023-01-21 17:11:55 +01:00
|
|
|
|
2024-03-05 23:23:06 +01:00
|
|
|
beforeEach(() => {
|
2023-08-25 19:44:52 +02:00
|
|
|
delete process.env.IMMICH_CONFIG_FILE;
|
2023-01-21 17:11:55 +01:00
|
|
|
configMock = newSystemConfigRepositoryMock();
|
2024-03-22 23:24:02 +01:00
|
|
|
eventMock = newEventRepositoryMock();
|
|
|
|
sut = new SystemConfigService(configMock, eventMock, smartInfoMock);
|
2023-01-21 17:11:55 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should work', () => {
|
|
|
|
expect(sut).toBeDefined();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('getDefaults', () => {
|
|
|
|
it('should return the default config', () => {
|
|
|
|
configMock.load.mockResolvedValue(updates);
|
|
|
|
|
2023-07-15 06:03:56 +02:00
|
|
|
expect(sut.getDefaults()).toEqual(defaults);
|
2023-01-21 17:11:55 +01:00
|
|
|
expect(configMock.load).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('getConfig', () => {
|
2023-12-21 02:47:56 +01:00
|
|
|
let warnLog: jest.SpyInstance;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
warnLog = jest.spyOn(ImmichLogger.prototype, 'warn');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
warnLog.mockRestore();
|
|
|
|
});
|
|
|
|
|
2023-01-21 17:11:55 +01:00
|
|
|
it('should return the default config', async () => {
|
|
|
|
configMock.load.mockResolvedValue([]);
|
|
|
|
|
2023-07-15 06:03:56 +02:00
|
|
|
await expect(sut.getConfig()).resolves.toEqual(defaults);
|
2023-01-21 17:11:55 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should merge the overrides', async () => {
|
|
|
|
configMock.load.mockResolvedValue([
|
2023-05-22 20:07:43 +02:00
|
|
|
{ key: SystemConfigKey.FFMPEG_CRF, value: 30 },
|
2023-01-21 17:11:55 +01:00
|
|
|
{ key: SystemConfigKey.OAUTH_AUTO_LAUNCH, value: true },
|
2023-10-06 09:01:14 +02:00
|
|
|
{ key: SystemConfigKey.TRASH_DAYS, value: 10 },
|
2024-03-06 06:45:40 +01:00
|
|
|
{ key: SystemConfigKey.USER_DELETE_DELAY, value: 15 },
|
2023-01-21 17:11:55 +01:00
|
|
|
]);
|
|
|
|
|
|
|
|
await expect(sut.getConfig()).resolves.toEqual(updatedConfig);
|
|
|
|
});
|
2023-08-25 19:44:52 +02:00
|
|
|
|
2024-03-12 16:29:49 +01:00
|
|
|
it('should load the config from a json file', async () => {
|
2023-08-25 19:44:52 +02:00
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.json';
|
2024-03-06 06:45:40 +01:00
|
|
|
const partialConfig = {
|
|
|
|
ffmpeg: { crf: 30 },
|
|
|
|
oauth: { autoLaunch: true },
|
|
|
|
trash: { days: 10 },
|
|
|
|
user: { deleteDelay: 15 },
|
|
|
|
};
|
2023-11-09 17:10:56 +01:00
|
|
|
configMock.readFile.mockResolvedValue(JSON.stringify(partialConfig));
|
2023-08-25 19:44:52 +02:00
|
|
|
|
|
|
|
await expect(sut.getConfig()).resolves.toEqual(updatedConfig);
|
|
|
|
|
|
|
|
expect(configMock.readFile).toHaveBeenCalledWith('immich-config.json');
|
|
|
|
});
|
|
|
|
|
2024-03-12 16:29:49 +01:00
|
|
|
it('should load the config from a yaml file', async () => {
|
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.yaml';
|
|
|
|
const partialConfig = `
|
|
|
|
ffmpeg:
|
|
|
|
crf: 30
|
|
|
|
oauth:
|
|
|
|
autoLaunch: true
|
|
|
|
trash:
|
|
|
|
days: 10
|
|
|
|
user:
|
|
|
|
deleteDelay: 15
|
|
|
|
`;
|
|
|
|
configMock.readFile.mockResolvedValue(partialConfig);
|
|
|
|
|
|
|
|
await expect(sut.getConfig()).resolves.toEqual(updatedConfig);
|
|
|
|
|
|
|
|
expect(configMock.readFile).toHaveBeenCalledWith('immich-config.yaml');
|
|
|
|
});
|
|
|
|
|
2023-08-25 19:44:52 +02:00
|
|
|
it('should accept an empty configuration file', async () => {
|
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.json';
|
2023-11-09 17:10:56 +01:00
|
|
|
configMock.readFile.mockResolvedValue(JSON.stringify({}));
|
2023-08-25 19:44:52 +02:00
|
|
|
|
|
|
|
await expect(sut.getConfig()).resolves.toEqual(defaults);
|
|
|
|
|
|
|
|
expect(configMock.readFile).toHaveBeenCalledWith('immich-config.json');
|
|
|
|
});
|
|
|
|
|
2023-10-17 23:34:16 +02:00
|
|
|
it('should allow underscores in the machine learning url', async () => {
|
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.json';
|
|
|
|
const partialConfig = { machineLearning: { url: 'immich_machine_learning' } };
|
2023-11-09 17:10:56 +01:00
|
|
|
configMock.readFile.mockResolvedValue(JSON.stringify(partialConfig));
|
2023-10-17 23:34:16 +02:00
|
|
|
|
|
|
|
const config = await sut.getConfig();
|
|
|
|
expect(config.machineLearning.url).toEqual('immich_machine_learning');
|
|
|
|
});
|
|
|
|
|
2024-03-12 16:29:49 +01:00
|
|
|
it('should warn for unknown options in yaml', async () => {
|
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.yaml';
|
|
|
|
const partialConfig = `
|
|
|
|
unknownOption: true
|
|
|
|
`;
|
|
|
|
configMock.readFile.mockResolvedValue(partialConfig);
|
|
|
|
|
|
|
|
await sut.getConfig();
|
|
|
|
expect(warnLog).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
2023-08-25 19:44:52 +02:00
|
|
|
const tests = [
|
|
|
|
{ should: 'validate numbers', config: { ffmpeg: { crf: 'not-a-number' } } },
|
|
|
|
{ should: 'validate booleans', config: { oauth: { enabled: 'invalid' } } },
|
|
|
|
{ should: 'validate enums', config: { ffmpeg: { transcode: 'unknown' } } },
|
|
|
|
{ should: 'validate required oauth fields', config: { oauth: { enabled: true } } },
|
2023-12-21 02:47:56 +01:00
|
|
|
{ should: 'warn for top level unknown options', warn: true, config: { unknownOption: true } },
|
|
|
|
{ should: 'warn for nested unknown options', warn: true, config: { ffmpeg: { unknownOption: true } } },
|
2023-08-25 19:44:52 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
for (const test of tests) {
|
|
|
|
it(`should ${test.should}`, async () => {
|
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.json';
|
2023-11-09 17:10:56 +01:00
|
|
|
configMock.readFile.mockResolvedValue(JSON.stringify(test.config));
|
2023-08-25 19:44:52 +02:00
|
|
|
|
2023-12-21 02:47:56 +01:00
|
|
|
if (test.warn) {
|
|
|
|
await sut.getConfig();
|
|
|
|
expect(warnLog).toHaveBeenCalled();
|
|
|
|
} else {
|
|
|
|
await expect(sut.getConfig()).rejects.toBeInstanceOf(Error);
|
|
|
|
}
|
2023-08-25 19:44:52 +02:00
|
|
|
});
|
|
|
|
}
|
2023-01-21 17:11:55 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('getStorageTemplateOptions', () => {
|
|
|
|
it('should send back the datetime variables', () => {
|
|
|
|
expect(sut.getStorageTemplateOptions()).toEqual({
|
|
|
|
dayOptions: ['d', 'dd'],
|
|
|
|
hourOptions: ['h', 'hh', 'H', 'HH'],
|
|
|
|
minuteOptions: ['m', 'mm'],
|
|
|
|
monthOptions: ['M', 'MM', 'MMM', 'MMMM'],
|
|
|
|
presetOptions: [
|
|
|
|
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
|
|
|
'{{y}}/{{MM}}-{{dd}}/{{filename}}',
|
|
|
|
'{{y}}/{{MMMM}}-{{dd}}/{{filename}}',
|
|
|
|
'{{y}}/{{MM}}/{{filename}}',
|
|
|
|
'{{y}}/{{MMM}}/{{filename}}',
|
|
|
|
'{{y}}/{{MMMM}}/{{filename}}',
|
|
|
|
'{{y}}/{{MM}}/{{dd}}/{{filename}}',
|
|
|
|
'{{y}}/{{MMMM}}/{{dd}}/{{filename}}',
|
|
|
|
'{{y}}/{{y}}-{{MM}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
|
|
|
'{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
|
|
|
'{{y}}-{{MMM}}-{{dd}}/{{filename}}',
|
|
|
|
'{{y}}-{{MMMM}}-{{dd}}/{{filename}}',
|
2023-03-01 14:10:01 +01:00
|
|
|
'{{y}}/{{y}}-{{MM}}/{{filename}}',
|
2023-09-28 19:47:31 +02:00
|
|
|
'{{y}}/{{y}}-{{WW}}/{{filename}}',
|
2023-10-20 23:17:17 +02:00
|
|
|
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{assetId}}',
|
|
|
|
'{{y}}/{{y}}-{{MM}}/{{assetId}}',
|
|
|
|
'{{y}}/{{y}}-{{WW}}/{{assetId}}',
|
2023-10-23 20:00:31 +02:00
|
|
|
'{{album}}/{{filename}}',
|
2023-01-21 17:11:55 +01:00
|
|
|
],
|
2024-03-15 21:13:08 +01:00
|
|
|
secondOptions: ['s', 'ss', 'SSS'],
|
2023-09-28 19:47:31 +02:00
|
|
|
weekOptions: ['W', 'WW'],
|
2023-01-21 17:11:55 +01:00
|
|
|
yearOptions: ['y', 'yy'],
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('updateConfig', () => {
|
2023-12-13 18:23:51 +01:00
|
|
|
it('should update the config and emit client and server events', async () => {
|
2023-01-21 17:11:55 +01:00
|
|
|
configMock.load.mockResolvedValue(updates);
|
|
|
|
|
|
|
|
await expect(sut.updateConfig(updatedConfig)).resolves.toEqual(updatedConfig);
|
|
|
|
|
2024-03-22 23:24:02 +01:00
|
|
|
expect(eventMock.clientBroadcast).toHaveBeenCalled();
|
|
|
|
expect(eventMock.serverSend).toHaveBeenCalledWith(ServerEvent.CONFIG_UPDATE, null);
|
2023-01-21 17:11:55 +01:00
|
|
|
expect(configMock.saveAll).toHaveBeenCalledWith(updates);
|
|
|
|
});
|
|
|
|
|
2023-08-25 19:44:52 +02:00
|
|
|
it('should throw an error if a config file is in use', async () => {
|
|
|
|
process.env.IMMICH_CONFIG_FILE = 'immich-config.json';
|
2023-11-09 17:10:56 +01:00
|
|
|
configMock.readFile.mockResolvedValue(JSON.stringify({}));
|
2023-08-25 19:44:52 +02:00
|
|
|
await expect(sut.updateConfig(defaults)).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
expect(configMock.saveAll).not.toHaveBeenCalled();
|
|
|
|
});
|
2023-01-21 17:11:55 +01:00
|
|
|
});
|
|
|
|
|
2023-11-18 05:13:36 +01:00
|
|
|
describe('getCustomCss', () => {
|
2023-10-26 00:13:05 +02:00
|
|
|
it('should return the default theme', async () => {
|
2023-11-18 05:13:36 +01:00
|
|
|
await expect(sut.getCustomCss()).resolves.toEqual(defaults.theme.customCss);
|
2023-10-26 00:13:05 +02:00
|
|
|
});
|
|
|
|
});
|
2023-01-21 17:11:55 +01:00
|
|
|
});
|