Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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: 2 additions & 0 deletions packages/app/scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export type Assets = {
assetItems: string;
assetItemFilters: string;
assetFilters: string;
contentItems: string;
};

export type AppManifest = {
Expand All @@ -245,6 +246,7 @@ export type AppxBundle = {
assetItems: string;
assetItemFilters: string;
assetFilters: string;
contentItems: string;
packageCertificate: string;
singleApp?: string;
};
Expand Down
195 changes: 123 additions & 72 deletions packages/app/test/windows/getBundleResources.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,100 @@ import { getBundleResources as getBundleResourcesActual } from "../../windows/pr
import { fs, setMockFiles } from "../fs.mock.mts";

describe("getBundleResources()", () => {
const getBundleResources: typeof getBundleResourcesActual = (p) =>
getBundleResourcesActual(p, fs);
const getBundleResources: typeof getBundleResourcesActual = (p, opts) =>
getBundleResourcesActual(p, opts, fs);

const legacyOpts = { useFabric: false };
const newArchOpts = { useFabric: true };

afterEach(() => setMockFiles());

it("returns app name and bundle resources", () => {
for (const opts of [legacyOpts, newArchOpts]) {
const arch = opts.useFabric ? "new" : "old";

it(`returns package manifest (${arch} arch)`, () => {
setMockFiles({
"app.json": JSON.stringify({
windows: {
appxManifest: "windows/Example/Package.appxmanifest",
},
}),
});

deepEqual(getBundleResources("app.json", opts), {
appName: "ReactTestApp",
singleApp: undefined,
appxManifest: "windows\\Example\\Package.appxmanifest",
assetItems: "",
assetItemFilters: "",
assetFilters: "",
contentItems: "",
packageCertificate: "",
});
});

it(`handles missing manifest (${arch} arch)`, (t) => {
const warnMock = t.mock.method(console, "warn", () => null);

deepEqual(getBundleResources("", opts), {
appName: "ReactTestApp",
appxManifest: "windows/Package.appxmanifest",
assetItems: "",
assetItemFilters: "",
assetFilters: "",
contentItems: "",
packageCertificate: "",
});

equal(
warnMock.mock.calls[0].arguments[1],
"Could not find 'app.json' file."
);
});

it(`handles invalid manifest (${arch} arch)`, (t) => {
const warnMock = t.mock.method(console, "warn", () => null);
setMockFiles({ "app.json": "-" });

deepEqual(getBundleResources("app.json", opts), {
appName: "ReactTestApp",
appxManifest: "windows/Package.appxmanifest",
assetItems: "",
assetItemFilters: "",
assetFilters: "",
contentItems: "",
packageCertificate: "",
});

match(
warnMock.mock.calls[0].arguments[1],
/^Could not parse 'app.json':\n/
);
});

it(`returns package certificate (${arch} arch)`, () => {
setMockFiles({
"app.json": JSON.stringify({
windows: {
certificateKeyFile: "windows/ReactTestApp_TemporaryKey.pfx",
certificateThumbprint: "thumbprint",
certificatePassword: "password",
},
}),
});

const { packageCertificate } = getBundleResources("app.json", opts);
equal(
packageCertificate,
`<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
<PackageCertificateKeyFile>$(ProjectRootDir)\\windows\\ReactTestApp_TemporaryKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>thumbprint</PackageCertificateThumbprint>
<PackageCertificatePassword>password</PackageCertificatePassword>`
);
});
}

it("returns app name and bundle resources (old arch)", () => {
const assets = path.join("dist", "assets");
const bundle = path.join("dist", "main.bundle");
setMockFiles({
Expand All @@ -28,7 +116,8 @@ describe("getBundleResources()", () => {
assetItems,
assetItemFilters,
assetFilters,
} = getBundleResources("app.json");
contentItems,
} = getBundleResources("app.json", legacyOpts);

equal(appName, "Example");
equal(appxManifest, "windows\\Package.appxmanifest");
Expand All @@ -54,83 +143,45 @@ describe("getBundleResources()", () => {
assetFilters,
/^<Filter Include="Assets\\assets">\s+<UniqueIdentifier>{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}<\/UniqueIdentifier>\s+<\/Filter>$/
);
equal(contentItems, "");
});

it("returns package manifest", () => {
it("returns app name and bundle resources (new arch)", () => {
const assets = path.join("dist", "assets");
const bundle = path.join("dist", "main.bundle");
setMockFiles({
"app.json": JSON.stringify({
windows: {
appxManifest: "windows/Example/Package.appxmanifest",
},
name: "Example",
resources: [assets, bundle],
}),
[path.join(assets, "app.json")]: "{}",
[bundle]: "'use strict';",
});

deepEqual(getBundleResources("app.json"), {
appName: "ReactTestApp",
singleApp: undefined,
appxManifest: "windows\\Example\\Package.appxmanifest",
assetItems: "",
assetItemFilters: "",
assetFilters: "",
packageCertificate: "",
});
});

it("handles missing manifest", (t) => {
const warnMock = t.mock.method(console, "warn", () => null);

deepEqual(getBundleResources(""), {
appName: "ReactTestApp",
appxManifest: "windows/Package.appxmanifest",
assetItems: "",
assetItemFilters: "",
assetFilters: "",
packageCertificate: "",
});

equal(
warnMock.mock.calls[0].arguments[1],
"Could not find 'app.json' file."
);
});

it("handles invalid manifest", (t) => {
const warnMock = t.mock.method(console, "warn", () => null);
setMockFiles({ "app.json": "-" });

deepEqual(getBundleResources("app.json"), {
appName: "ReactTestApp",
appxManifest: "windows/Package.appxmanifest",
assetItems: "",
assetItemFilters: "",
assetFilters: "",
packageCertificate: "",
});

match(
warnMock.mock.calls[0].arguments[1],
/^Could not parse 'app.json':\n/
);
});

it("returns package certificate", () => {
setMockFiles({
"app.json": JSON.stringify({
windows: {
certificateKeyFile: "windows/ReactTestApp_TemporaryKey.pfx",
certificateThumbprint: "thumbprint",
certificatePassword: "password",
},
}),
});
const {
appName,
appxManifest,
assetItems,
assetItemFilters,
assetFilters,
contentItems,
} = getBundleResources("app.json", newArchOpts);

const { packageCertificate } = getBundleResources("app.json");
equal(appName, "Example");
equal(appxManifest, "windows\\Package.appxmanifest");
equal(assetItems, "");
equal(assetItemFilters, "");
equal(assetFilters, "");
equal(
packageCertificate,
`<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
<PackageCertificateKeyFile>$(ProjectRootDir)\\windows\\ReactTestApp_TemporaryKey.pfx</PackageCertificateKeyFile>
<PackageCertificateThumbprint>thumbprint</PackageCertificateThumbprint>
<PackageCertificatePassword>password</PackageCertificatePassword>`
contentItems,
`<Content Include="$(ProjectRootDir)\\dist\\assets\\app.json">
<Link>Bundle\\assets\\app.json</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(ProjectRootDir)\\dist\\main.bundle">
<Link>Bundle\\main.bundle</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>`
);
});
});
90 changes: 67 additions & 23 deletions packages/app/test/windows/parseResources.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,59 @@ import { parseResources as parseResourcesActual } from "../../windows/project.mj
import { fs, setMockFiles } from "../fs.mock.mts";

describe("parseResources()", () => {
const parseResources: typeof parseResourcesActual = (r, p) =>
parseResourcesActual(r, p, fs);
const parseResources: typeof parseResourcesActual = (r, p, opts) =>
parseResourcesActual(r, p, opts, fs);

const empty = { assetFilters: "", assetItemFilters: "", assetItems: "" };
const empty = {
assetFilters: "",
assetItemFilters: "",
assetItems: "",
contentItems: "",
};

const legacyOpts = { useFabric: false };
const newArchOpts = { useFabric: true };

afterEach(() => setMockFiles());

it("returns empty strings for no resources", () => {
deepEqual(parseResources(undefined, ""), empty);
deepEqual(parseResources([], ""), empty);
deepEqual(parseResources({}, ""), empty);
deepEqual(parseResources({ windows: [] }, ""), empty);
});
for (const opts of [legacyOpts, newArchOpts]) {
const arch = opts.useFabric ? "new" : "old";

it(`returns empty strings for no resources (${arch} arch)`, () => {
deepEqual(parseResources(undefined, "", opts), empty);
deepEqual(parseResources([], "", opts), empty);
deepEqual(parseResources({}, "", opts), empty);
deepEqual(parseResources({ windows: [] }, "", opts), empty);
});

it(`skips missing assets (${arch} arch)`, (t) => {
const warnMock = t.mock.method(console, "warn", () => null);

const resources = ["dist/assets", "dist/main.bundle"];

deepEqual(parseResources(resources, ".", opts), empty);

equal(
warnMock.mock.calls[0].arguments[1],
"Resource not found: dist/assets"
);
equal(
warnMock.mock.calls[1].arguments[1],
"Resource not found: dist/main.bundle"
);
});
}

it("returns references to existing assets", () => {
it("returns references to existing assets (old arch)", () => {
setMockFiles({
"dist/assets/node_modules/arnold/portrait.png": "{}",
"dist/assets/splash.png": "{}",
"dist/main.jsbundle": "'use strict';",
});

const { assetItems, assetItemFilters, assetFilters } = parseResources(
["dist/assets", "dist/main.jsbundle"],
"."
);
const { assetItems, assetItemFilters, assetFilters, contentItems } =
parseResources(["dist/assets", "dist/main.jsbundle"], ".", legacyOpts);

equal(
assetItems,
`<CopyFileToFolders Include="$(ProjectRootDir)\\dist\\assets\\node_modules\\arnold\\portrait.png">
Expand Down Expand Up @@ -57,20 +85,36 @@ describe("parseResources()", () => {
assetFilters,
/^<Filter Include="Assets\\assets">\s+<UniqueIdentifier>{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}<\/UniqueIdentifier>\s+<\/Filter>\s+<Filter Include="Assets\\assets\\node_modules">\s+<UniqueIdentifier>{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}<\/UniqueIdentifier>\s+<\/Filter>\s+<Filter Include="Assets\\assets\\node_modules\\arnold">\s+<UniqueIdentifier>{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}<\/UniqueIdentifier>\s+<\/Filter>$/
);
equal(contentItems, "");
});

it("skips missing assets", (t) => {
const warnMock = t.mock.method(console, "warn", () => null);
it("returns references to existing assets (new arch)", () => {
setMockFiles({
"dist/assets/node_modules/arnold/portrait.png": "{}",
"dist/assets/splash.png": "{}",
"dist/main.jsbundle": "'use strict';",
});

deepEqual(parseResources(["dist/assets", "dist/main.bundle"], "."), empty);
const { assetItems, assetItemFilters, assetFilters, contentItems } =
parseResources(["dist/assets", "dist/main.jsbundle"], ".", newArchOpts);

equal(assetItems, "");
equal(assetItemFilters, "");
equal(assetFilters, "");
equal(
warnMock.mock.calls[0].arguments[1],
"Resource not found: dist/assets"
);
equal(
warnMock.mock.calls[1].arguments[1],
"Resource not found: dist/main.bundle"
contentItems,
`<Content Include="$(ProjectRootDir)\\dist\\assets\\node_modules\\arnold\\portrait.png">
<Link>Bundle\\assets\\node_modules\\arnold\\portrait.png</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(ProjectRootDir)\\dist\\assets\\splash.png">
<Link>Bundle\\assets\\splash.png</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(ProjectRootDir)\\dist\\main.jsbundle">
<Link>Bundle\\main.jsbundle</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>`
);
});
});
Loading
Loading