Skip to content

Commit

Permalink
fix(telemetry): handle malformed telemetry tokens (#3014)
Browse files Browse the repository at this point in the history
handle the scenario that a user has an Ionic configuration file,
but does not have a 'tokens.telemetry' field in said file.

STENCIL-85: ionic-pwa fails at startup
  • Loading branch information
rwaskiewicz committed Aug 24, 2021
1 parent 6d8a61d commit ff75a47
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
7 changes: 6 additions & 1 deletion src/cli/ionic-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export interface TelemetryConfig {
'tokens.telemetry'?: string;
}

/**
* Reads an Ionic configuration file from disk, parses it, and performs any necessary corrections to it if ceratin
* values are deemed to be malformed
* @returns the config read from disk that has been potentially been updated
*/
export async function readConfig(): Promise<TelemetryConfig> {
let config: TelemetryConfig = await readJson(defaultConfig());

Expand All @@ -25,7 +30,7 @@ export async function readConfig(): Promise<TelemetryConfig> {
};

await writeConfig(config);
} else if (!!config && !config['tokens.telemetry'].match(UUID_REGEX)) {
} else if (!UUID_REGEX.test(config['tokens.telemetry'])) {
const newUuid = uuidv4();
await writeConfig({ ...config, 'tokens.telemetry': newUuid });
config['tokens.telemetry'] = newUuid;
Expand Down
7 changes: 6 additions & 1 deletion src/cli/telemetry/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ export function uuidv4(): string {
});
}

export async function readJson(path: string) {
/**
* Reads and parses a JSON file from the given `path`
* @param path the path on the file system to read and parse
* @returns the parsed JSON
*/
export async function readJson(path: string): Promise<any> {
const file = await getCompilerSystem().readFile(path);
return !!file && JSON.parse(file);
}
Expand Down
42 changes: 32 additions & 10 deletions src/cli/test/ionic-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,56 @@ describe('readConfig', () => {
args: [],
});

it('should create a file if it does not exist', async () => {
let result = await getCompilerSystem().stat(defaultConfig());

if (result.isFile) {
await getCompilerSystem().removeFile(defaultConfig());
}
beforeEach(async () => {
await getCompilerSystem().removeFile(defaultConfig());
});

result = await getCompilerSystem().stat(defaultConfig());
it('should create a file if it does not exist', async () => {
const result = await getCompilerSystem().stat(defaultConfig());

// expect the file to have been deleted by the test setup
expect(result.isFile).toBe(false);

const config = await readConfig();

expect(Object.keys(config).join()).toBe('tokens.telemetry,telemetry.stencil');
});

it('should fix the telemetry token if necessary', async () => {
it("should fix the telemetry token if it's a string, but an invalid UUID", async () => {
await writeConfig({ 'telemetry.stencil': true, 'tokens.telemetry': 'aaaa' });

let result = await getCompilerSystem().stat(defaultConfig());
const result = await getCompilerSystem().stat(defaultConfig());

expect(result.isFile).toBe(true);

const config = await readConfig();

expect(Object.keys(config).join()).toBe('telemetry.stencil,tokens.telemetry');
expect(config['telemetry.stencil']).toBe(true);
expect(!!config['tokens.telemetry'].match(UUID_REGEX)).toBe(true);
expect(config['tokens.telemetry']).toMatch(UUID_REGEX);
});

it('handles a non-string telemetry token', async () => {
// our typings state that `tokens.telemetry` is of type `string | undefined`, but technically this value could be
// anything. use `undefined` to make the typings happy (this should cover all non-string telemetry tokens). the
// important thing here is that the value is _not_ a string for this test!
await writeConfig({ 'telemetry.stencil': true, 'tokens.telemetry': undefined });

const config = await readConfig();

expect(Object.keys(config).join()).toBe('telemetry.stencil,tokens.telemetry');
expect(config['telemetry.stencil']).toBe(true);
expect(config['tokens.telemetry']).toMatch(UUID_REGEX);
});

it('handles a non-existent telemetry token', async () => {
await writeConfig({ 'telemetry.stencil': true });

const config = await readConfig();

expect(Object.keys(config).join()).toBe('telemetry.stencil,tokens.telemetry');
expect(config['telemetry.stencil']).toBe(true);
expect(config['tokens.telemetry']).toMatch(UUID_REGEX);
});

it('should read a file if it exists', async () => {
Expand Down

0 comments on commit ff75a47

Please sign in to comment.