@expo/fingerprint 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,8 @@ import { vol, fs as volFS } from 'memfs';
5
5
  import path from 'path';
6
6
  import resolveFrom from 'resolve-from';
7
7
 
8
- import { normalizeOptions } from '../../Options';
8
+ import { HashSourceContents } from '../../Fingerprint.types';
9
+ import { normalizeOptionsAsync } from '../../Options';
9
10
  import {
10
11
  getEasBuildSourcesAsync,
11
12
  getExpoAutolinkingAndroidSourcesAsync,
@@ -55,7 +56,7 @@ describe(getEasBuildSourcesAsync, () => {
55
56
  }`
56
57
  );
57
58
 
58
- const sources = await getEasBuildSourcesAsync('/app', normalizeOptions());
59
+ const sources = await getEasBuildSourcesAsync('/app', await normalizeOptionsAsync('/app'));
59
60
  expect(sources).toContainEqual(
60
61
  expect.objectContaining({
61
62
  type: 'file',
@@ -97,7 +98,10 @@ describe('getExpoAutolinkingSourcesAsync', () => {
97
98
  });
98
99
 
99
100
  it('should contain expo autolinking projects', async () => {
100
- let sources = await getExpoAutolinkingAndroidSourcesAsync('/app', normalizeOptions());
101
+ let sources = await getExpoAutolinkingAndroidSourcesAsync(
102
+ '/app',
103
+ await normalizeOptionsAsync('/app')
104
+ );
101
105
  expect(sources).toContainEqual(
102
106
  expect.objectContaining({
103
107
  type: 'dir',
@@ -106,7 +110,7 @@ describe('getExpoAutolinkingSourcesAsync', () => {
106
110
  );
107
111
  expect(sources).toMatchSnapshot();
108
112
 
109
- sources = await getExpoAutolinkingIosSourcesAsync('/app', normalizeOptions());
113
+ sources = await getExpoAutolinkingIosSourcesAsync('/app', await normalizeOptionsAsync('/app'));
110
114
  expect(sources).toContainEqual(
111
115
  expect.objectContaining({ type: 'dir', filePath: 'node_modules/expo-modules-core' })
112
116
  );
@@ -114,14 +118,17 @@ describe('getExpoAutolinkingSourcesAsync', () => {
114
118
  });
115
119
 
116
120
  it('should not containt absolute path in contents', async () => {
117
- let sources = await getExpoAutolinkingAndroidSourcesAsync('/app', normalizeOptions());
121
+ let sources = await getExpoAutolinkingAndroidSourcesAsync(
122
+ '/app',
123
+ await normalizeOptionsAsync('/app')
124
+ );
118
125
  for (const source of sources) {
119
126
  if (source.type === 'contents') {
120
127
  expect(source.contents.indexOf('/app/')).toBe(-1);
121
128
  }
122
129
  }
123
130
 
124
- sources = await getExpoAutolinkingIosSourcesAsync('/app', normalizeOptions());
131
+ sources = await getExpoAutolinkingIosSourcesAsync('/app', await normalizeOptionsAsync('/app'));
125
132
  for (const source of sources) {
126
133
  if (source.type === 'contents') {
127
134
  expect(source.contents.indexOf('/app/')).toBe(-1);
@@ -147,26 +154,67 @@ describe(getExpoConfigSourcesAsync, () => {
147
154
  // To fake the case as no expo installed, trying to resolve as **nonexist/expo/config** module
148
155
  return actualResolver(fromDirectory, 'nonexist/expo/config');
149
156
  });
150
- const sources = await getExpoConfigSourcesAsync('/app', normalizeOptions());
157
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
151
158
  expect(sources.length).toBe(0);
152
159
  });
153
160
 
154
- it('should contain app.json', async () => {
161
+ it('should contain expo config', async () => {
155
162
  vol.fromJSON(require('./fixtures/ExpoManaged47Project.json'));
156
- const sources = await getExpoConfigSourcesAsync('/app', normalizeOptions());
157
- expect(sources).toContainEqual(
158
- expect.objectContaining({
159
- type: 'file',
160
- filePath: 'app.json',
161
- })
163
+ const appJson = JSON.parse(vol.readFileSync('/app/app.json', 'utf8').toString());
164
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
165
+ const expoConfigSource = sources.find<HashSourceContents>(
166
+ (source): source is HashSourceContents =>
167
+ source.type === 'contents' && source.id === 'expoConfig'
168
+ );
169
+ const expoConfig = JSON.parse(expoConfigSource?.contents?.toString() ?? 'null');
170
+ expect(expoConfig).not.toBeNull();
171
+ expect(expoConfig.name).toEqual(appJson.expo.name);
172
+ });
173
+
174
+ it('should not contain runtimeVersion in expo config', async () => {
175
+ vol.fromJSON(require('./fixtures/ExpoManaged47Project.json'));
176
+ vol.writeFileSync(
177
+ '/app/app.config.js',
178
+ `\
179
+ export default ({ config }) => {
180
+ config.runtimeVersion = '1.0.0';
181
+ return config;
182
+ };`
183
+ );
184
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
185
+ const expoConfigSource = sources.find<HashSourceContents>(
186
+ (source): source is HashSourceContents =>
187
+ source.type === 'contents' && source.id === 'expoConfig'
162
188
  );
189
+ const expoConfig = JSON.parse(expoConfigSource?.contents?.toString() ?? 'null');
190
+ expect(expoConfig).not.toBeNull();
191
+ expect(expoConfig.runtimeVersion).toBeUndefined();
192
+ });
193
+
194
+ it('should keep expo config contents in deterministic order', async () => {
195
+ vol.fromJSON(require('./fixtures/ExpoManaged47Project.json'));
196
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
197
+
198
+ const appJsonContents = vol.readFileSync('/app/app.json', 'utf8').toString();
199
+ const appJson = JSON.parse(appJsonContents);
200
+ const { name } = appJson.expo;
201
+ // Re-insert name to change the object order
202
+ delete appJson.expo.name;
203
+ appJson.expo.name = name;
204
+ const newAppJsonContents = JSON.stringify(appJson);
205
+ expect(newAppJsonContents).not.toEqual(appJsonContents);
206
+ vol.writeFileSync('/app/app.json', newAppJsonContents);
207
+
208
+ // Even new app.json contents changed its order, the source contents should be the same.
209
+ const sources2 = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
210
+ expect(sources).toEqual(sources2);
163
211
  });
164
212
 
165
213
  it('should contain external icon file in app.json', async () => {
166
214
  vol.fromJSON(require('./fixtures/ExpoManaged47Project.json'));
167
215
  vol.mkdirSync('/app/assets');
168
216
  vol.writeFileSync('/app/assets/icon.png', 'PNG data');
169
- const sources = await getExpoConfigSourcesAsync('/app', normalizeOptions());
217
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
170
218
  expect(sources).toContainEqual(
171
219
  expect.objectContaining({
172
220
  type: 'file',
@@ -221,7 +269,7 @@ describe(`getExpoConfigSourcesAsync - config-plugins`, () => {
221
269
  },
222
270
  })
223
271
  );
224
- const sources = await getExpoConfigSourcesAsync('/app', normalizeOptions());
272
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
225
273
  expect(sources).toContainEqual(
226
274
  expect.objectContaining({
227
275
  type: 'dir',
@@ -243,7 +291,7 @@ describe(`getExpoConfigSourcesAsync - config-plugins`, () => {
243
291
  },
244
292
  })
245
293
  );
246
- const sources = await getExpoConfigSourcesAsync('/app', normalizeOptions());
294
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
247
295
  expect(sources).toContainEqual(
248
296
  expect.objectContaining({
249
297
  type: 'dir',
@@ -260,7 +308,7 @@ export default ({ config }) => {
260
308
  return config;
261
309
  };`
262
310
  );
263
- const sources = await getExpoConfigSourcesAsync('/app', normalizeOptions());
311
+ const sources = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
264
312
 
265
313
  vol.writeFileSync(
266
314
  '/app/app.config.js',
@@ -272,9 +320,16 @@ export default ({ config }) => {
272
320
  return config;
273
321
  };`
274
322
  );
275
- const sources2 = await getExpoConfigSourcesAsync('/app', normalizeOptions());
323
+ const sources2 = await getExpoConfigSourcesAsync('/app', await normalizeOptionsAsync('/app'));
276
324
 
277
- expect(sources).toEqual(sources2);
325
+ // sources2 will contain the plugins from expo config, but sources will not.
326
+ const sourcesWithoutExpoConfig = sources.filter(
327
+ (item) => item.type !== 'contents' || item.id !== 'expoConfig'
328
+ );
329
+ const sources2WithoutExpoConfig = sources2.filter(
330
+ (item) => item.type !== 'contents' || item.id !== 'expoConfig'
331
+ );
332
+ expect(sourcesWithoutExpoConfig).toEqual(sources2WithoutExpoConfig);
278
333
  });
279
334
  });
280
335
 
@@ -1,6 +1,6 @@
1
1
  import { vol } from 'memfs';
2
2
 
3
- import { normalizeOptions } from '../../Options';
3
+ import { normalizeOptionsAsync } from '../../Options';
4
4
  import { getPatchPackageSourcesAsync } from '../PatchPackage';
5
5
  import { getHashSourcesAsync } from '../Sourcer';
6
6
 
@@ -16,7 +16,7 @@ describe(getPatchPackageSourcesAsync, () => {
16
16
  vol.fromJSON(require('./fixtures/ExpoManaged47Project.json'));
17
17
  vol.fromJSON(require('./fixtures/PatchPackage.json'));
18
18
 
19
- const sources = await getPatchPackageSourcesAsync('/app', normalizeOptions());
19
+ const sources = await getPatchPackageSourcesAsync('/app', await normalizeOptionsAsync('/app'));
20
20
  expect(sources).toContainEqual(
21
21
  expect.objectContaining({
22
22
  type: 'dir',
@@ -41,7 +41,7 @@ describe('patch-package postinstall', () => {
41
41
  { virtual: true }
42
42
  );
43
43
 
44
- const sources = await getHashSourcesAsync('/app', normalizeOptions());
44
+ const sources = await getHashSourcesAsync('/app', await normalizeOptionsAsync('/app'));
45
45
  expect(sources).toContainEqual(
46
46
  expect.objectContaining({
47
47
  type: 'contents',
@@ -1,11 +1,11 @@
1
- import { normalizeOptions } from '../../Options';
1
+ import { normalizeOptionsAsync } from '../../Options';
2
2
  import { getHashSourcesAsync } from '../Sourcer';
3
3
 
4
4
  describe(getHashSourcesAsync, () => {
5
5
  it('should include `extraSources` from input parameter', async () => {
6
6
  const sources = await getHashSourcesAsync(
7
7
  '/app',
8
- normalizeOptions({
8
+ await normalizeOptionsAsync('/app', {
9
9
  extraSources: [{ type: 'dir', filePath: '/app/scripts', reasons: ['extra'] }],
10
10
  })
11
11
  );
@@ -0,0 +1,41 @@
1
+ import { stringifyJsonSorted } from '../Utils';
2
+
3
+ describe(stringifyJsonSorted, () => {
4
+ it('should support primitive types', () => {
5
+ expect(stringifyJsonSorted(1)).toEqual('1');
6
+ expect(stringifyJsonSorted('s')).toEqual('"s"');
7
+ expect(stringifyJsonSorted(true)).toEqual('true');
8
+ expect(stringifyJsonSorted(false)).toEqual('false');
9
+ expect(stringifyJsonSorted(null)).toEqual('null');
10
+ });
11
+
12
+ it('should sort array', () => {
13
+ expect(stringifyJsonSorted([])).toEqual('[]');
14
+ expect(stringifyJsonSorted([2, 'a', 1, false, 6, 4, 5, 's', 3, 0, true, 1, 1])).toEqual(
15
+ '["a","s",0,1,1,1,2,3,4,5,6,false,true]'
16
+ );
17
+ });
18
+
19
+ it('should sort object by keys', () => {
20
+ expect(stringifyJsonSorted({})).toEqual('{}');
21
+ expect(stringifyJsonSorted({ c: '1', a: '3', b: '2' })).toEqual('{"a":"3","b":"2","c":"1"}');
22
+ expect(
23
+ stringifyJsonSorted({ c: '1', a: '3', b: '2', nested: { c: '1', a: '3', b: '2' } })
24
+ ).toEqual('{"a":"3","b":"2","c":"1","nested":{"a":"3","b":"2","c":"1"}}');
25
+ });
26
+
27
+ it('should support mixed array/object', () => {
28
+ expect(stringifyJsonSorted([{ b: '2' }, { c: '1' }, { a: '3' }])).toEqual(
29
+ '[{"a":"3"},{"b":"2"},{"c":"1"}]'
30
+ );
31
+ expect(stringifyJsonSorted([{ b: '2' }, {}, { a: '3' }, null])).toEqual(
32
+ '[null,{"a":"3"},{"b":"2"},{}]'
33
+ );
34
+ expect(
35
+ stringifyJsonSorted({
36
+ array: [3, 2, 1],
37
+ nestedData: { nestedArray: [{ b: '2' }, { c: '1' }, { a: '3' }] },
38
+ })
39
+ ).toEqual('{"array":[1,2,3],"nestedData":{"nestedArray":[{"a":"3"},{"b":"2"},{"c":"1"}]}}');
40
+ });
41
+ });