1import { fs } from 'memfs';
2import path from 'path';
3import temporary from 'tempy';
4
5import * as GitIgnore from '../mergeGitIgnorePaths';
6
7const testRoot = temporary.directory();
8beforeAll(async () => {
9  await fs.promises.mkdir(testRoot, { recursive: true });
10});
11afterAll(async () => {
12  await fs.promises.rm(testRoot, { recursive: true, force: true });
13});
14
15const gitignore1 = `
16# hello world
17*/foo
18
19ios/
20
21/android
22## bar
23
24`;
25
26// A gitignore with an old generated section
27const gitignore2 = `a
28b
29${GitIgnore.createGeneratedHeaderComment('...')}
30foo
31bar
32${GitIgnore.generatedFooterComment}
33c
34d`;
35
36// A broken generated section
37const gitignore3 = `a
38b
39${GitIgnore.createGeneratedHeaderComment('...')}
40foo
41bar
42c
43d`;
44
45// Footer is before header
46const gitignore4 = `a
47b
48${GitIgnore.generatedFooterComment}
49foo
50bar
51${GitIgnore.createGeneratedHeaderComment('...')}
52c
53d`;
54
55it(`sanitizes comments, new lines, and sort order`, () => {
56  expect(GitIgnore.getSanitizedGitIgnoreLines(gitignore1)).toStrictEqual([
57    '*/foo',
58    '/android ',
59    'ios/',
60  ]);
61});
62
63describe('removeGeneratedGitIgnoreContents', () => {
64  it(`removes a generated gitignore`, () => {
65    expect(GitIgnore.removeGeneratedGitIgnoreContents(gitignore2)?.split('\n')).toStrictEqual([
66      'a',
67      'b',
68      'c',
69      'd',
70    ]);
71  });
72  it(`removes nothing from a regular gitignore`, () => {
73    expect(GitIgnore.removeGeneratedGitIgnoreContents(gitignore1)).toBe(null);
74  });
75  it(`removes nothing when the generated footer is missing`, () => {
76    expect(GitIgnore.removeGeneratedGitIgnoreContents(gitignore3)).toBe(null);
77  });
78  it(`removes nothing when the footer precede the header`, () => {
79    expect(GitIgnore.removeGeneratedGitIgnoreContents(gitignore4)).toBe(null);
80  });
81});
82
83describe('mergeGitIgnore', () => {
84  it(`skips merging if the target file is missing`, async () => {
85    // fs
86    const projectRoot = path.join(testRoot, 'merge-git-ignore-skip-when-target-missing');
87    await fs.promises.mkdir(projectRoot, { recursive: true });
88    // Setup
89
90    const targetGitIgnorePath = path.join(projectRoot, '.gitignore');
91    // Skip writing a gitignore
92
93    const sourceGitIgnorePath = path.join(projectRoot, '.gitignore-other');
94    await fs.promises.writeFile(
95      sourceGitIgnorePath,
96      [
97        'alpha',
98        'beta',
99        // in the future we may want to merge this value with the existing matching value
100        // or maybe we could keep the code simple and not do that :]
101        'bar',
102      ].join('\n')
103    );
104
105    expect(GitIgnore.mergeGitIgnorePaths(targetGitIgnorePath, sourceGitIgnorePath)).toBe(null);
106    expect(fs.existsSync(targetGitIgnorePath)).toBe(false);
107  });
108  it(`merges two git ignore files in the filesystem`, async () => {
109    // fs
110    const projectRoot = path.join(testRoot, 'merge-git-ignore-works');
111    await fs.promises.mkdir(projectRoot, { recursive: true });
112    // Setup
113    const targetGitIgnorePath = path.join(projectRoot, '.gitignore');
114    await fs.promises.writeFile(
115      targetGitIgnorePath,
116      [
117        'foo',
118        // Test a duplicate value
119        'bar',
120      ].join('\n')
121    );
122
123    const sourceGitIgnorePath = path.join(projectRoot, '.gitignore-other');
124    await fs.promises.writeFile(
125      sourceGitIgnorePath,
126      [
127        'alpha',
128        'beta',
129        // in the future we may want to merge this value with the existing matching value
130        // or maybe we could keep the code simple and not do that :]
131        'bar',
132      ].join('\n')
133    );
134
135    const results = GitIgnore.mergeGitIgnorePaths(targetGitIgnorePath, sourceGitIgnorePath);
136    expect(results).not.toBe(null);
137    expect(results.contents).toMatch(
138      /generated expo-cli sync-69a5afdba5ff28bbd11618f94ae2dc4bfdfd7cae/
139    );
140    expect(results.contents).toMatch(/foo/);
141    expect(results.contents).toMatch(/alpha/);
142    expect(results.didMerge).toBe(true);
143
144    expect(fs.readFileSync(targetGitIgnorePath, 'utf8')).toBe(results.contents);
145  });
146});
147