This commit changes the web application's build, transpilation and minification process from Vue CLI to Vite. This shift paves the way for a full migration to Vite as the primary build tool (#230). Configuration changes: - `.vscode/extensions.json`: Update recommended plugins, replacing unmaintained ones with official recommendations. - Legacy browser support: - Use `@vitejs/plugin-legacy` to transpile for older browsers. - Remove `core-js` dependency and `babel.config.cjs` configuration as they're now handled by the legacy plugin. - Delete `@babel/preset-typescript` and `@babel/preset-typescript` dependencies as legacy plugin handles babel dependencies by default. - Add `terser` dependency that's used by the legacy plugin for minification, as per Vite's official documentation. - `tsconfig.json`: - Remove obsolete `webpack-env` types. - Add `"resolveJsonModule": true` to be able to read JSON files in right way. - Use correct casing as configuration values. - Simplify `lib` to align with Vite and Vue starter configuration. - Add `"skipLibCheck": true` as `npm run build` now runs `tsc` which fails on inconsistent typings inside `node_modules` due to npm's weak dependency resoultion. - PostCSS: - Add `autoprefixer` as dependency, no longer installed by Vue CLI. - Epxlicitly added `postcss` as dependency to anticipate potential peer dependency changes. - Remove related `@vue/cli` dependencies. - Remove `sass-loader` as Vite has native CSS preprocessing support. - Run integration tests with `jsdom` environment so `window` object can be used. Client-side changes: - Abstract build tool specific environment variable population. Environment variables were previously populated by Vue CLI and now by Vite but not having an abstraction caused issues. This abstraction solves build errors and allows easier future migrations and testing. - Change Vue CLI-specific `~@` aliases to `@` to be able to compile with Vite. - Update types in LiquorTree to satisfy `tsc`. - Remove Vue CLI-specific workaround from `src/presentation/main.ts`. Restructuring: - Move `public/` to `presentation/` to align with the layered structure, which was not possible with Vue CLI. - Move `index.html` to web root instead of having it inside `public/` to align with official recommended structure. - Move logic shared by both integration and unit tests to `tests/shared`. - Move logo creation script to `scripts/` and its npm command to include `build` to align with rest of the structure.
223 lines
8.0 KiB
TypeScript
223 lines
8.0 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { ProjectInformation } from '@/domain/ProjectInformation';
|
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
|
import { EnumRangeTestRunner } from '@tests/unit/application/Common/EnumRangeTestRunner';
|
|
import { VersionStub } from '@tests/unit/shared/Stubs/VersionStub';
|
|
import { Version } from '@/domain/Version';
|
|
import { PropertyKeys } from '@tests/shared/TypeHelpers';
|
|
|
|
describe('ProjectInformation', () => {
|
|
describe('retrieval of property values', () => {
|
|
interface IInformationParsingTestCase {
|
|
readonly description?: string;
|
|
readonly expectedValue: string;
|
|
readonly buildWithExpectedValue: (
|
|
builder: ProjectInformationBuilder,
|
|
expected: string,
|
|
) => ProjectInformationBuilder;
|
|
readonly getActualValue: (sut: ProjectInformation) => string;
|
|
}
|
|
const propertyTestCases: {
|
|
readonly [K in PropertyKeys<ProjectInformation>]: readonly IInformationParsingTestCase[];
|
|
} = {
|
|
name: [{
|
|
expectedValue: 'expected-app-name',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withName(expected),
|
|
getActualValue: (sut) => sut.name,
|
|
}],
|
|
version: [{
|
|
expectedValue: '0.11.3',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withVersion(new VersionStub(expected)),
|
|
getActualValue: (sut) => sut.version.toString(),
|
|
}],
|
|
slogan: [{
|
|
expectedValue: 'expected-slogan',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withSlogan(expected),
|
|
getActualValue: (sut) => sut.slogan,
|
|
}],
|
|
repositoryUrl: [{
|
|
description: 'without `.git` suffix',
|
|
expectedValue: 'expected-repository-url',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withRepositoryUrl(expected),
|
|
getActualValue: (sut) => sut.repositoryUrl,
|
|
}, {
|
|
description: 'with `.git` suffix',
|
|
expectedValue: 'expected-repository-url',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withRepositoryUrl(expected),
|
|
getActualValue: (sut) => sut.repositoryUrl,
|
|
}],
|
|
repositoryWebUrl: [{
|
|
description: 'without `.git` suffix',
|
|
expectedValue: 'expected-repository-url',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withRepositoryUrl(expected),
|
|
getActualValue: (sut) => sut.repositoryWebUrl,
|
|
}, {
|
|
description: 'with `.git` suffix',
|
|
expectedValue: 'expected-repository-url',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withRepositoryUrl(`${expected}.git`),
|
|
getActualValue: (sut) => sut.repositoryWebUrl,
|
|
}],
|
|
homepage: [{
|
|
expectedValue: 'expected-homepage',
|
|
buildWithExpectedValue: (builder, expected) => builder
|
|
.withHomepage(expected),
|
|
getActualValue: (sut) => sut.homepage,
|
|
}],
|
|
feedbackUrl: [{
|
|
description: 'without `.git` suffix',
|
|
expectedValue: 'https://github.com/undergroundwires/privacy.sexy/issues',
|
|
buildWithExpectedValue: (builder) => builder
|
|
.withRepositoryUrl('https://github.com/undergroundwires/privacy.sexy'),
|
|
getActualValue: (sut) => sut.feedbackUrl,
|
|
}, {
|
|
description: 'with `.git` suffix',
|
|
expectedValue: 'https://github.com/undergroundwires/privacy.sexy/issues',
|
|
buildWithExpectedValue: (builder) => builder
|
|
.withRepositoryUrl('https://github.com/undergroundwires/privacy.sexy.git'),
|
|
getActualValue: (sut) => sut.feedbackUrl,
|
|
}],
|
|
releaseUrl: [{
|
|
description: 'without `.git` suffix',
|
|
expectedValue: 'https://github.com/undergroundwires/privacy.sexy/releases/tag/0.7.2',
|
|
buildWithExpectedValue: (builder) => builder
|
|
.withRepositoryUrl('https://github.com/undergroundwires/privacy.sexy')
|
|
.withVersion(new VersionStub('0.7.2')),
|
|
getActualValue: (sut) => sut.releaseUrl,
|
|
}, {
|
|
description: 'with `.git` suffix',
|
|
expectedValue: 'https://github.com/undergroundwires/privacy.sexy/releases/tag/0.7.2',
|
|
buildWithExpectedValue: (builder) => builder
|
|
.withRepositoryUrl('https://github.com/undergroundwires/privacy.sexy.git')
|
|
.withVersion(new VersionStub('0.7.2')),
|
|
getActualValue: (sut) => sut.releaseUrl,
|
|
}],
|
|
};
|
|
Object.entries(propertyTestCases).forEach(([propertyName, testList]) => {
|
|
testList.forEach(({
|
|
description, buildWithExpectedValue, expectedValue, getActualValue,
|
|
}) => {
|
|
it(`${propertyName}${description ? ` (${description})` : ''}`, () => {
|
|
// arrange
|
|
const builder = new ProjectInformationBuilder();
|
|
const sut = buildWithExpectedValue(builder, expectedValue).build();
|
|
|
|
// act
|
|
const actual = getActualValue(sut);
|
|
|
|
// assert
|
|
expect(actual).to.equal(expectedValue);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
describe('correct retrieval of download URL per operating system', () => {
|
|
const testCases: ReadonlyArray<{
|
|
readonly os: OperatingSystem,
|
|
readonly expected: string,
|
|
readonly repositoryUrl: string,
|
|
readonly version: string,
|
|
}> = [
|
|
{
|
|
os: OperatingSystem.macOS,
|
|
expected: 'https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.2/privacy.sexy-0.7.2.dmg',
|
|
repositoryUrl: 'https://github.com/undergroundwires/privacy.sexy.git',
|
|
version: '0.7.2',
|
|
},
|
|
{
|
|
os: OperatingSystem.Linux,
|
|
expected: 'https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.2/privacy.sexy-0.7.2.AppImage',
|
|
repositoryUrl: 'https://github.com/undergroundwires/privacy.sexy.git',
|
|
version: '0.7.2',
|
|
},
|
|
{
|
|
os: OperatingSystem.Windows,
|
|
expected: 'https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.2/privacy.sexy-Setup-0.7.2.exe',
|
|
repositoryUrl: 'https://github.com/undergroundwires/privacy.sexy.git',
|
|
version: '0.7.2',
|
|
},
|
|
];
|
|
for (const testCase of testCases) {
|
|
it(`should return the expected download URL for ${OperatingSystem[testCase.os]}`, () => {
|
|
// arrange
|
|
const {
|
|
expected, version, repositoryUrl, os,
|
|
} = testCase;
|
|
const sut = new ProjectInformationBuilder()
|
|
.withVersion(new VersionStub(version))
|
|
.withRepositoryUrl(repositoryUrl)
|
|
.build();
|
|
// act
|
|
const actual = sut.getDownloadUrl(os);
|
|
// assert
|
|
expect(actual).to.equal(expected);
|
|
});
|
|
}
|
|
it('should throw an error when provided with an invalid operating system', () => {
|
|
// arrange
|
|
const sut = new ProjectInformationBuilder()
|
|
.build();
|
|
// act
|
|
const act = (os: OperatingSystem) => sut.getDownloadUrl(os);
|
|
// assert
|
|
new EnumRangeTestRunner(act)
|
|
.testOutOfRangeThrows()
|
|
.testAbsentValueThrows()
|
|
.testInvalidValueThrows(OperatingSystem.KaiOS, `Unsupported os: ${OperatingSystem[OperatingSystem.KaiOS]}`);
|
|
});
|
|
});
|
|
});
|
|
|
|
class ProjectInformationBuilder {
|
|
private name = 'default-name';
|
|
|
|
private version: Version = new VersionStub();
|
|
|
|
private repositoryUrl = 'default-repository-url';
|
|
|
|
private homepage = 'default-homepage';
|
|
|
|
private slogan = 'default-slogan';
|
|
|
|
public withName(name: string): ProjectInformationBuilder {
|
|
this.name = name;
|
|
return this;
|
|
}
|
|
|
|
public withVersion(version: VersionStub): ProjectInformationBuilder {
|
|
this.version = version;
|
|
return this;
|
|
}
|
|
|
|
public withSlogan(slogan: string): ProjectInformationBuilder {
|
|
this.slogan = slogan;
|
|
return this;
|
|
}
|
|
|
|
public withRepositoryUrl(repositoryUrl: string): ProjectInformationBuilder {
|
|
this.repositoryUrl = repositoryUrl;
|
|
return this;
|
|
}
|
|
|
|
public withHomepage(homepage: string): ProjectInformationBuilder {
|
|
this.homepage = homepage;
|
|
return this;
|
|
}
|
|
|
|
public build(): ProjectInformation {
|
|
return new ProjectInformation(
|
|
this.name,
|
|
this.version,
|
|
this.slogan,
|
|
this.repositoryUrl,
|
|
this.homepage,
|
|
);
|
|
}
|
|
}
|