Skip to content

Commit

Permalink
feature!: move snack runtime URLs to snack-content and add EAS Upda…
Browse files Browse the repository at this point in the history
…te URLs (#527)

* feature(snack-content): add snack runtime url helpers in base library

* chore(snack-sdk): re-export snack runtime url helpers from `snack-content`

* feature(snack-content): add `parseSnackRuntimeUrl` helper

* feature!(snack-sdk): use `createSnackRuntimeUrl` when creating device links

* refactor(runtime): use `parseSnackUrl` instead of own url helpers

* fix(website): pass `testTransports` properly for new and old url formats

* chore: bump package lockfile

* fix(runtime): update `testTransport` tests

* chore(snack-content): resolve linting issue

* refactor(snack-content): unify the `parseEASUpdateSnackRuntimeUrl` if statements
  • Loading branch information
byCedric committed Jan 11, 2024
1 parent 8c7801a commit e46845a
Show file tree
Hide file tree
Showing 14 changed files with 466 additions and 81 deletions.
1 change: 1 addition & 0 deletions packages/snack-content/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
preset: 'ts-jest',
rootDir: 'src',
prettierPath: require.resolve('jest-prettier'),
};
1 change: 1 addition & 0 deletions packages/snack-content/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"eslint": "^8.49.0",
"eslint-config-universe": "^12.0.0",
"jest": "^27.5.1",
"jest-prettier": "npm:prettier@^2.8.8",
"prettier": "^3.0.3",
"rimraf": "^3.0.2",
"ts-jest": "~27.1.3",
Expand Down
227 changes: 227 additions & 0 deletions packages/snack-content/src/__tests__/urls-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import {
createSnackRuntimeUrl,
parseSnackRuntimeUrl,
createEASUpdateSnackRuntimeUrl,
createClassicUpdateSnackRuntimeUrl,
parseEASUpdateSnackRuntimeUrl,
parseClassicUpdateSnackRuntimeUrl,
} from '../urls';

describe(createSnackRuntimeUrl, () => {
const channel = 'xy!z1_';

it('creates classic updates url with "channel" and "sdkVersion"', () => {
expect(createSnackRuntimeUrl({ channel, sdkVersion: '49.0.1' })).toMatchInlineSnapshot(
`"exp://exp.host/@snack/sdk.49.0.0-xy!z1_"`,
);
});

it('creates eas update url with "channel" and "sdkVersion" >= 50', () => {
expect(createSnackRuntimeUrl({ channel, sdkVersion: '50.0.0' })).toMatchInlineSnapshot(
`"exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=xy%21z1_&runtime-version=exposdk%3A50.0.0"`,
);
});
});

describe(parseSnackRuntimeUrl, () => {
it('parses classic updates url with "channel" and "sdkVersion"', () => {
expect(parseSnackRuntimeUrl('exp://exp.host/@snack/sdk.49.0.0-xy!z1_')).toMatchInlineSnapshot(`
Object {
"channel": "xy!z1_",
"sdkVersion": "49.0.0",
}
`);
});

it('parses eas update url with "channel" and "sdkVersion"', () => {
expect(
parseSnackRuntimeUrl(
'exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=xy%21z1_&runtime-version=exposdk%3A50.0.0',
),
).toMatchInlineSnapshot(`
Object {
"channel": "xy!z1_",
"sdkVersion": "50.0.0",
}
`);
});
});

describe(createEASUpdateSnackRuntimeUrl, () => {
const channel = 'xy!z1_';
const snack = 'JxS_FUOcGz';

it('creates url with "channel"', () => {
expect(createEASUpdateSnackRuntimeUrl({ channel })).toMatchInlineSnapshot(
'"exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=xy%21z1_"',
);
});

it('creates url with "channel" and "sdkVersion"', () => {
expect(createEASUpdateSnackRuntimeUrl({ channel, sdkVersion: '50.0.1' })).toMatchInlineSnapshot(
'"exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=xy%21z1_&runtime-version=exposdk%3A50.0.0"',
);
});

it('creates url with "channel, "sdkVersion", and "snack"', () => {
expect(
createEASUpdateSnackRuntimeUrl({ channel, snack, sdkVersion: 50 }),
).toMatchInlineSnapshot(
'"exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack=JxS_FUOcGz&snack-channel=xy%21z1_&runtime-version=exposdk%3A50.0.0"',
);
});
});

describe(parseEASUpdateSnackRuntimeUrl, () => {
const channel = 'xy%21z1_';
const snack = 'JxS_FUOcGz';
const sdkVersion = 'exposdk%3A50.0.0';

it('parses url without any parameters', () => {
expect(
parseEASUpdateSnackRuntimeUrl('exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824'),
).toMatchInlineSnapshot(`Object {}`);
});

it('parses url with "channel"', () => {
expect(
parseEASUpdateSnackRuntimeUrl(
`exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=${channel}`,
),
).toMatchInlineSnapshot(`
Object {
"channel": "xy!z1_",
}
`);
});

it('parses url with "channel" and "sdkVersion"', () => {
expect(
parseEASUpdateSnackRuntimeUrl(
`exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=${channel}&runtime-version=${sdkVersion}`,
),
).toMatchInlineSnapshot(`
Object {
"channel": "xy!z1_",
"sdkVersion": "50.0.0",
}
`);
});

it('parses url with "channel", "sdkVersion", and "snack"', () => {
expect(
parseEASUpdateSnackRuntimeUrl(
`exp://u.expo.dev/933fd9c0-1666-11e7-afca-d980795c5824?snack-channel=${channel}&runtime-version=${sdkVersion}&snack=${snack}`,
),
).toMatchInlineSnapshot(`
Object {
"channel": "xy!z1_",
"sdkVersion": "50.0.0",
"snack": "JxS_FUOcGz",
}
`);
});

it('parses redirected url with "channel", "sdkVersion", and "snack"', () => {
expect(
parseEASUpdateSnackRuntimeUrl(
`exp://snack.expo.app?snack-channel=${channel}&runtime-version=${sdkVersion}&snack=${snack}`,
),
).toMatchInlineSnapshot(`
Object {
"channel": "xy!z1_",
"sdkVersion": "50.0.0",
"snack": "JxS_FUOcGz",
}
`);
});
});

describe(createClassicUpdateSnackRuntimeUrl, () => {
const channel = 'qWeqG1!';

it('creates url using format "exp://exp.host/@snack/sdk.<sdkVersion>-<channel>"', () => {
expect(
createClassicUpdateSnackRuntimeUrl({ channel, sdkVersion: '49.0.9' }),
).toMatchInlineSnapshot('"exp://exp.host/@snack/sdk.49.0.0-qWeqG1!"');
});

it('creates url using format "exp://exp.host/@snack/<snack>+<channel>"', () => {
expect(
createClassicUpdateSnackRuntimeUrl({ snack: 'snack-name', sdkVersion: '48.0.0' }),
).toMatchInlineSnapshot('"exp://exp.host/@snack/snack-name"');

expect(
createClassicUpdateSnackRuntimeUrl({ channel, snack: 'snack-name', sdkVersion: '47.0.0' }),
).toMatchInlineSnapshot('"exp://exp.host/@snack/snack-name+qWeqG1!"');
});

it('creates url using format "exp://exp.host/@<owner>/<name>+<channel>"', () => {
expect(
createClassicUpdateSnackRuntimeUrl({
snack: '@owner-name/snack-name',
sdkVersion: '48.0.0',
}),
).toMatchInlineSnapshot('"exp://exp.host/@owner-name/snack-name"');

expect(
createClassicUpdateSnackRuntimeUrl({
channel,
snack: '@owner-name/snack-name',
sdkVersion: '48.0.0',
}),
).toMatchInlineSnapshot('"exp://exp.host/@owner-name/snack-name+qWeqG1!"');
});

it('throws for format "exp://exp.host/@snack/sdk.<sdkVersion>-<channel>" without "sdkVersion"', () => {
expect(() => createClassicUpdateSnackRuntimeUrl({ channel })).toThrowError(
'Cannot create classic updates URL with only "channel", "sdkVersion" is required',
);
});

it('throws without "snack" or "channel"', () => {
expect(() => createClassicUpdateSnackRuntimeUrl({})).toThrowError(
'Cannot create classic updates URL without "channel" or "snack"',
);
});
});

describe(parseClassicUpdateSnackRuntimeUrl, () => {
it('parses url without any paramters', () => {
expect(parseClassicUpdateSnackRuntimeUrl('exp://exp.host')).toMatchInlineSnapshot(`Object {}`);
});

it('parses url using format "exp://exp.host/@snack/sdk.<sdkVersion>-<channel>"', () => {
expect(parseClassicUpdateSnackRuntimeUrl('exp://exp.host/@snack/sdk.49.0.0-qWeqG1!'))
.toMatchInlineSnapshot(`
Object {
"channel": "qWeqG1!",
"sdkVersion": "49.0.0",
}
`);
});

it('parses url using format "exp://exp.host/@snack/<snack>+<channel>"', () => {
// We ignore these formats, as we can't determine the Snack without owner
expect(
parseClassicUpdateSnackRuntimeUrl('exp://exp.host/@snack/snack-name'),
).toMatchInlineSnapshot(`Object {}`);

expect(parseClassicUpdateSnackRuntimeUrl('exp://exp.host/@snack/snack-name+qWeqG1!'))
.toMatchInlineSnapshot(`
Object {
"channel": "qWeqG1!",
}
`);
});

it('parses url using format "exp://exp.host/@<owner>/<name>+<channel>"', () => {
expect(parseClassicUpdateSnackRuntimeUrl('exp://exp.host/@owner-name/snack-name+qWeqG1!'))
.toMatchInlineSnapshot(`
Object {
"channel": "qWeqG1!",
"snack": "@owner-name/snack-name",
}
`);
});
});
1 change: 1 addition & 0 deletions packages/snack-content/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './defaults';
export * from './sdk';
export { default as sdks } from './sdks';
export * from './types';
export * from './urls';
Loading

0 comments on commit e46845a

Please sign in to comment.