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
5 changes: 4 additions & 1 deletion lib/controllers/prepare-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,10 @@ export class PrepareController
prepareData: IPrepareData,
projectData: IProjectData,
): Promise<IPrepareResultData> {
await this.$projectService.ensureAppResourcesExist(projectData.projectDir);
await this.$projectService.ensureAppResourcesExist(
projectData.projectDir,
this.$mobileHelper.normalizePlatformName(prepareData.platform),
);
await this.$platformController.addPlatformIfNeeded(
prepareData,
projectData,
Expand Down
6 changes: 5 additions & 1 deletion lib/definitions/project.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,12 @@ interface IProjectService {
* Checks if App_Resources exists, or pulls down a fresh set
* from the default template otherwise.
* @param {string} projectDir
* @param {string} platformDirName When set, also adds App_Resources/<platformDirName> from the default template if it is missing.
*/
ensureAppResourcesExist(projectDir: string): Promise<void>;
ensureAppResourcesExist(
projectDir: string,
platformDirName?: string,
): Promise<void>;
}

interface INsConfigPlaform {
Expand Down
52 changes: 40 additions & 12 deletions lib/services/project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,10 @@ export class ProjectService implements IProjectService {
}

@performanceLog()
public async ensureAppResourcesExist(projectDir: string): Promise<void> {
public async ensureAppResourcesExist(
projectDir: string,
platformDirName?: string
): Promise<void> {
const projectData = this.$projectDataService.getProjectData(projectDir);
const appResourcesDestinationPath = projectData.getAppResourcesDirectoryPath(
projectDir
Expand All @@ -235,23 +238,48 @@ export class ProjectService implements IProjectService {
"Project does not have App_Resources - fetching from default template."
);
this.$fs.createDirectory(appResourcesDestinationPath);
const tempDir = await this.$tempService.mkdirSync("ns-default-template");
// the template installed doesn't have App_Resources -> get from a default template
await this.$pacoteService.extractPackage(
constants.RESERVED_TEMPLATE_NAMES["default"],
tempDir
);
const templateProjectData = this.$projectDataService.getProjectData(
tempDir
);
const templateAppResourcesDir = templateProjectData.getAppResourcesDirectoryPath(
tempDir
);
const templateAppResourcesDir = await this.getDefaultTemplateAppResourcesDir();
this.$fs.copyFile(
path.join(templateAppResourcesDir, "*"),
appResourcesDestinationPath
);
return;
}

// An app created before a platform was supported (e.g. Windows) has no folder for it.
if (
platformDirName &&
!this.$fs.exists(path.join(appResourcesDestinationPath, platformDirName))
) {
const templateAppResourcesDir = await this.getDefaultTemplateAppResourcesDir();
const templatePlatformDir = path.join(
templateAppResourcesDir,
platformDirName
);
if (!this.$fs.exists(templatePlatformDir)) {
this.$logger.warn(
`App_Resources/${platformDirName} is missing and the default template does not provide one.`
);
return;
}
this.$logger.info(
`Adding App_Resources/${platformDirName} from the default template.`
);
this.$fs.copyFile(templatePlatformDir, appResourcesDestinationPath);
}
}

private async getDefaultTemplateAppResourcesDir(): Promise<string> {
const tempDir = await this.$tempService.mkdirSync("ns-default-template");
await this.$pacoteService.extractPackage(
constants.RESERVED_TEMPLATE_NAMES["default"],
tempDir
);
const templateProjectData = this.$projectDataService.getProjectData(
tempDir
);
return templateProjectData.getAppResourcesDirectoryPath(tempDir);
}

@performanceLog()
Expand Down
95 changes: 95 additions & 0 deletions test/project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,99 @@ describe("projectService", () => {
assert.isFalse(projectService.isValidNativeScriptProject("some-dir"));
});
});

describe("ensureAppResourcesExist", () => {
const projectDir = path.resolve("app-resources-project");
const appResources = path.join(projectDir, "App_Resources");
const templateDir = path.resolve("default-template");
const templateAppResources = path.join(templateDir, "App_Resources");

const setup = (existing: string[]) => {
const exists = new Set(existing.map((p) => path.resolve(p)));
const copies: { from: string; to: string }[] = [];
let extracted = 0;
const testInjector = new yok.Yok();
testInjector.register("fs", {
exists: (p: string) => exists.has(path.resolve(p)),
createDirectory: (p: string) => exists.add(path.resolve(p)),
copyFile: (from: string, to: string) => copies.push({ from, to }),
});
testInjector.register("logger", LoggerStub);
testInjector.register("projectDataService", {
getProjectData: (dir: string): IProjectData =>
<any>{
getAppResourcesDirectoryPath: (d: string) =>
path.join(d === templateDir ? templateDir : dir, "App_Resources"),
},
});
testInjector.register("pacoteService", {
extractPackage: async () => {
extracted++;
},
});
testInjector.register("tempService", {
mkdirSync: async () => templateDir,
});
for (const name of [
"options",
"hooksService",
"packageManager",
"errors",
"projectConfigService",
"projectHelper",
"projectNameService",
"projectTemplatesService",
"staticConfig",
"childProcess",
]) {
testInjector.register(name, {});
}
const projectService: IProjectService = testInjector.resolve(
ProjectServiceLib.ProjectService
);
return { projectService, copies, extracted: () => extracted };
};

it("copies the whole App_Resources when it is missing", async () => {
const { projectService, copies } = setup([]);
await projectService.ensureAppResourcesExist(projectDir, "Windows");
assert.deepEqual(copies, [
{ from: path.join(templateAppResources, "*"), to: appResources },
]);
});

it("adds a missing platform folder from the default template", async () => {
const { projectService, copies } = setup([
appResources,
path.join(templateAppResources, "Windows"),
]);
await projectService.ensureAppResourcesExist(projectDir, "Windows");
assert.deepEqual(copies, [
{ from: path.join(templateAppResources, "Windows"), to: appResources },
]);
});

it("leaves an existing platform folder alone", async () => {
const { projectService, copies, extracted } = setup([
appResources,
path.join(appResources, "Windows"),
]);
await projectService.ensureAppResourcesExist(projectDir, "Windows");
assert.deepEqual(copies, []);
assert.equal(extracted(), 0);
});

it("copies nothing when the template has no folder for the platform", async () => {
const { projectService, copies } = setup([appResources]);
await projectService.ensureAppResourcesExist(projectDir, "Windows");
assert.deepEqual(copies, []);
});

it("does not look at platform folders without a platform", async () => {
const { projectService, copies, extracted } = setup([appResources]);
await projectService.ensureAppResourcesExist(projectDir);
assert.deepEqual(copies, []);
assert.equal(extracted(), 0);
});
});
});
Loading