diff --git a/packages/insomnia-app/app/sync/git/__tests__/git-vcs.test.js b/packages/insomnia-app/app/sync/git/__tests__/git-vcs.test.js index d565cc10fa..a7e509bafe 100644 --- a/packages/insomnia-app/app/sync/git/__tests__/git-vcs.test.js +++ b/packages/insomnia-app/app/sync/git/__tests__/git-vcs.test.js @@ -5,7 +5,14 @@ import path from 'path'; jest.mock('path'); describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { - beforeAll(() => path.__mockPath(type)); + let fooTxt = ''; + let barTxt = ''; + beforeAll(() => { + path.__mockPath(type); + fooTxt = path.join(GIT_INSOMNIA_DIR, 'foo.txt'); + barTxt = path.join(GIT_INSOMNIA_DIR, 'bar.txt'); + }); + afterAll(() => jest.restoreAllMocks()); beforeEach(setupDateMocks); @@ -21,7 +28,8 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { const files1 = await vcs.listFiles(); expect(files1).toEqual([]); - await fs.promises.writeFile('/foo.txt', 'bar'); + // File does not exist in git index + await fs.promises.writeFile('foo.txt', 'bar'); const files2 = await vcs.listFiles(); expect(files2).toEqual([]); }); @@ -29,8 +37,8 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { it('stage and unstage file', async () => { const fs = MemPlugin.createPlugin(); await fs.promises.mkdir(GIT_INSOMNIA_DIR); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/foo.txt`, 'foo'); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/bar.txt`, 'bar'); + await fs.promises.writeFile(fooTxt, 'foo'); + await fs.promises.writeFile(barTxt, 'bar'); // Files outside namespace should be ignored await fs.promises.writeFile('/other.txt', 'other'); @@ -39,16 +47,16 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { await vcs.init(GIT_CLONE_DIR, fs); await vcs.setAuthor('Karen Brown', 'karen@example.com'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('*added'); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('*added'); - await vcs.add(`${GIT_INSOMNIA_DIR}/foo.txt`); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('added'); + await vcs.add(fooTxt); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('added'); - await vcs.remove(`${GIT_INSOMNIA_DIR}/foo.txt`); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('*added'); + await vcs.remove(fooTxt); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('*added'); }); it('Returns empty log without first commit', async () => { @@ -62,20 +70,20 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { it('commit file', async () => { const fs = MemPlugin.createPlugin(); - await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}`); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/foo.txt`, 'foo'); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/bar.txt`, 'bar'); + await fs.promises.mkdir(GIT_INSOMNIA_DIR); + await fs.promises.writeFile(fooTxt, 'foo'); + await fs.promises.writeFile(barTxt, 'bar'); - await fs.promises.writeFile('/other.txt', 'should be ignored'); + await fs.promises.writeFile('other.txt', 'should be ignored'); const vcs = new GitVCS(); await vcs.init(GIT_CLONE_DIR, fs); await vcs.setAuthor('Karen Brown', 'karen@example.com'); - await vcs.add(`${GIT_INSOMNIA_DIR}/foo.txt`); + await vcs.add(fooTxt); await vcs.commit('First commit!'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('unmodified'); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('unmodified'); expect(await vcs.log()).toEqual([ { @@ -98,36 +106,36 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { }, ]); - await fs.promises.unlink(`${GIT_INSOMNIA_DIR}/foo.txt`); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('*deleted'); + await fs.promises.unlink(fooTxt); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('*deleted'); - await vcs.remove(`${GIT_INSOMNIA_DIR}/foo.txt`); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('deleted'); + await vcs.remove(fooTxt); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('deleted'); - await vcs.remove(`${GIT_INSOMNIA_DIR}/foo.txt`); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added'); - expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('deleted'); + await vcs.remove(fooTxt); + expect(await vcs.status(barTxt)).toBe('*added'); + expect(await vcs.status(fooTxt)).toBe('deleted'); }); it('create branch', async () => { const fs = MemPlugin.createPlugin(); - await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}`); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/foo.txt`, 'foo'); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/bar.txt`, 'bar'); + await fs.promises.mkdir(GIT_INSOMNIA_DIR); + await fs.promises.writeFile(fooTxt, 'foo'); + await fs.promises.writeFile(barTxt, 'bar'); const vcs = new GitVCS(); await vcs.init(GIT_CLONE_DIR, fs); await vcs.setAuthor('Karen Brown', 'karen@example.com'); - await vcs.add(`${GIT_INSOMNIA_DIR}/foo.txt`); + await vcs.add(fooTxt); await vcs.commit('First commit!'); expect((await vcs.log()).length).toBe(1); await vcs.checkout('new-branch'); expect((await vcs.log()).length).toBe(1); - await vcs.add(`${GIT_INSOMNIA_DIR}/bar.txt`); + await vcs.add(barTxt); await vcs.commit('Second commit!'); expect((await vcs.log()).length).toBe(2); @@ -139,26 +147,27 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => { describe('readObjectFromTree()', () => { it('reads an object from tree', async () => { const fs = MemPlugin.createPlugin(); - await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}`); - await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}/dir`); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/dir/foo.txt`, 'foo'); + const dir = path.join(GIT_INSOMNIA_DIR, 'dir'); + const dirFooTxt = path.join(dir, 'foo.txt'); + + await fs.promises.mkdir(GIT_INSOMNIA_DIR); + await fs.promises.mkdir(dir); + await fs.promises.writeFile(dirFooTxt, 'foo'); const vcs = new GitVCS(); await vcs.init(GIT_CLONE_DIR, fs); await vcs.setAuthor('Karen Brown', 'karen@example.com'); - await vcs.add(`${GIT_INSOMNIA_DIR}/dir/foo.txt`); + await vcs.add(dirFooTxt); await vcs.commit('First'); - await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/dir/foo.txt`, 'foo bar'); - await vcs.add(`${GIT_INSOMNIA_DIR}/dir/foo.txt`); + await fs.promises.writeFile(dirFooTxt, 'foo bar'); + await vcs.add(dirFooTxt); await vcs.commit('Second'); const log = await vcs.log(); - expect(await vcs.readObjFromTree(log[0].tree, `${GIT_INSOMNIA_DIR}/dir/foo.txt`)).toBe( - 'foo bar', - ); - expect(await vcs.readObjFromTree(log[1].tree, `${GIT_INSOMNIA_DIR}/dir/foo.txt`)).toBe('foo'); + expect(await vcs.readObjFromTree(log[0].tree, dirFooTxt)).toBe('foo bar'); + expect(await vcs.readObjFromTree(log[1].tree, dirFooTxt)).toBe('foo'); // Some extra checks expect(await vcs.readObjFromTree(log[1].tree, 'missing')).toBe(null); diff --git a/packages/insomnia-app/app/sync/git/__tests__/mem-plugin.test.js b/packages/insomnia-app/app/sync/git/__tests__/mem-plugin.test.js index 6a7f495f17..68cef4392a 100644 --- a/packages/insomnia-app/app/sync/git/__tests__/mem-plugin.test.js +++ b/packages/insomnia-app/app/sync/git/__tests__/mem-plugin.test.js @@ -9,68 +9,72 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => { afterAll(() => jest.restoreAllMocks()); beforeEach(setupDateMocks); + const fooTxt = 'foo.txt'; + const barTxt = 'bar.txt'; + describe('readfile()', () => { it('fails to read', async () => { const p = new MemPlugin(); - await assertAsyncError(p.readFile('/foo.txt'), 'ENOENT'); + await assertAsyncError(p.readFile(fooTxt), 'ENOENT'); }); it('reads a file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'Hello World!'); - expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World!'); + await p.writeFile(fooTxt, 'Hello World!'); + expect((await p.readFile(fooTxt)).toString()).toBe('Hello World!'); }); }); describe('writeFile()', () => { it('fails to write over directory', async () => { const p = new MemPlugin(); + const dirName = 'foo'; - await p.mkdir('/foo'); - await assertAsyncError(p.writeFile('/foo', 'Hello World 2!'), 'EISDIR'); + await p.mkdir(dirName); + await assertAsyncError(p.writeFile(dirName, 'Hello World 2!'), 'EISDIR'); }); it('overwrites file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'Hello World!'); - await p.writeFile('/foo.txt', 'Hello World 2!'); - expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World 2!'); + await p.writeFile(fooTxt, 'Hello World!'); + await p.writeFile(fooTxt, 'Hello World 2!'); + expect((await p.readFile(fooTxt)).toString()).toBe('Hello World 2!'); }); it('flag "a" file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'Hello World!', { flag: 'a' }); - await p.writeFile('/foo.txt', 'xxx', { flag: 'a' }); - expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World!xxx'); + await p.writeFile(fooTxt, 'Hello World!', { flag: 'a' }); + await p.writeFile(fooTxt, 'xxx', { flag: 'a' }); + expect((await p.readFile(fooTxt)).toString()).toBe('Hello World!xxx'); }); it('flags "ax" and "wx" fail if path exists', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'Hello World!'); - await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'ax' }), 'EEXIST'); - await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'wx' }), 'EEXIST'); + await p.writeFile(fooTxt, 'Hello World!'); + await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'ax' }), 'EEXIST'); + await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'wx' }), 'EEXIST'); }); it('fails if flag "r"', async () => { const p = new MemPlugin(); - await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'r' }), 'EBADF'); + await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'r' }), 'EBADF'); }); it('fails if dir missing', async () => { const p = new MemPlugin(); - await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'r' }), 'EBADF'); + await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'r' }), 'EBADF'); }); it('works with flags', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'Hello World!', { flag: 'a' }); - await p.writeFile('/foo.txt', 'xxx', { flag: 'a' }); - expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World!xxx'); + await p.writeFile(fooTxt, 'Hello World!', { flag: 'a' }); + await p.writeFile(fooTxt, 'xxx', { flag: 'a' }); + expect((await p.readFile(fooTxt)).toString()).toBe('Hello World!xxx'); }); }); @@ -78,15 +82,15 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => { it('unlinks file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'xxx'); - await p.unlink('/foo.txt'); - await assertAsyncError(p.readFile('/foo.txt'), 'ENOENT'); + await p.writeFile(fooTxt, 'xxx'); + await p.unlink(fooTxt); + await assertAsyncError(p.readFile(fooTxt), 'ENOENT'); }); it('fails to unlinks missing file', async () => { const p = new MemPlugin(); - await assertAsyncError(p.unlink('/not/exist.txt'), 'ENOENT'); + await assertAsyncError(p.unlink(path.join('not', 'exist.txt')), 'ENOENT'); }); }); @@ -98,81 +102,90 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => { expect(await p.readdir(GIT_CLONE_DIR)).toEqual([]); // Write a file and list it again - await p.writeFile('/foo.txt', 'Hello World!'); - await p.writeFile('/bar.txt', 'Bar!'); + await p.writeFile(fooTxt, 'Hello World!'); + await p.writeFile(barTxt, 'Bar!'); expect(await p.readdir(GIT_CLONE_DIR)).toEqual(['bar.txt', 'foo.txt']); }); it('errors on file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'Bar!'); - await assertAsyncError(p.readdir('/foo.txt'), 'ENOTDIR'); + await p.writeFile(fooTxt, 'Bar!'); + await assertAsyncError(p.readdir(fooTxt), 'ENOTDIR'); }); it('errors on missing directory', async () => { const p = new MemPlugin(); - await assertAsyncError(p.readdir('/invalid'), 'ENOENT'); + await assertAsyncError(p.readdir(path.join('/', 'invalid')), 'ENOENT'); }); }); describe('mkdir()', () => { + const fooDir = 'foo'; + const fooBarDir = path.join(fooDir, 'bar'); + const cloneFooDir = path.join(GIT_CLONE_DIR, 'foo'); + const cloneFooBarDir = path.join(GIT_CLONE_DIR, 'foo', 'bar'); + const cloneFooBarBazDir = path.join(GIT_CLONE_DIR, 'foo', 'bar', 'baz'); + it('creates directory', async () => { const p = new MemPlugin(); - await p.mkdir('/foo'); - await p.mkdir('/foo/bar'); + await p.mkdir(fooDir); + await p.mkdir(fooBarDir); expect(await p.readdir(GIT_CLONE_DIR)).toEqual(['foo']); - expect(await p.readdir(`${GIT_CLONE_DIR}/foo`)).toEqual(['bar']); + expect(await p.readdir(cloneFooDir)).toEqual(['bar']); }); it('creates directory non-recursively', async () => { const p = new MemPlugin(); - await p.mkdir(`${GIT_CLONE_DIR}/foo`, { recursive: true }); - await p.mkdir(`${GIT_CLONE_DIR}/foo/bar`); - expect(await p.readdir(`${GIT_CLONE_DIR}/foo/bar`)).toEqual([]); + await p.mkdir(cloneFooDir, { recursive: true }); + await p.mkdir(cloneFooBarDir); + expect(await p.readdir(cloneFooBarDir)).toEqual([]); }); it('creates directory recursively', async () => { const p = new MemPlugin(); - await p.mkdir(`${GIT_CLONE_DIR}/foo/bar/baz`, { recursive: true }); - expect(await p.readdir(`${GIT_CLONE_DIR}/foo/bar/baz`)).toEqual([]); + await p.mkdir(cloneFooBarBazDir, { recursive: true }); + expect(await p.readdir(cloneFooBarBazDir)).toEqual([]); }); it('fails to create if no parent', async () => { const p = new MemPlugin(); - await assertAsyncError(p.mkdir(`${GIT_CLONE_DIR}/foo/bar/baz`), 'ENOENT'); + await assertAsyncError(p.mkdir(cloneFooBarBazDir), 'ENOENT'); }); }); describe('rmdir()', () => { + const abDir = path.join('a', 'b'); + const abcDir = path.join('a', 'b', 'c'); + it('removes a dir', async () => { const p = new MemPlugin(); - await p.mkdir('/a/b/c', { recursive: true }); - expect(await p.readdir('/a/b')).toEqual(['c']); - await p.rmdir('/a/b/c'); - expect(await p.readdir('/a/b')).toEqual([]); + await p.mkdir(abcDir, { recursive: true }); + expect(await p.readdir(abDir)).toEqual(['c']); + await p.rmdir(abcDir); + expect(await p.readdir(abDir)).toEqual([]); }); it('fails on non-empty dir', async () => { const p = new MemPlugin(); - await p.mkdir('/a/b/c', { recursive: true }); - await p.writeFile('/a/b/c/foo.txt', 'xxx'); + await p.mkdir(abcDir, { recursive: true }); + await p.writeFile(path.join(abcDir, 'foo.txt'), 'xxx'); - await assertAsyncError(p.rmdir('/a/b'), 'ENOTEMPTY'); - await assertAsyncError(p.rmdir('/a/b/c'), 'ENOTEMPTY'); + await assertAsyncError(p.rmdir(abDir), 'ENOTEMPTY'); + await assertAsyncError(p.rmdir(abcDir), 'ENOTEMPTY'); }); it('fails on file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'xxx'); - await assertAsyncError(p.rmdir('/foo.txt'), 'ENOTDIR'); + await p.writeFile(fooTxt, 'xxx'); + await assertAsyncError(p.rmdir(fooTxt), 'ENOTDIR'); }); }); @@ -202,8 +215,8 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => { it('stats file', async () => { const p = new MemPlugin(); - await p.writeFile('/foo.txt', 'xxx'); - const stat = await p.stat('/foo.txt'); + await p.writeFile(fooTxt, 'xxx'); + const stat = await p.stat(fooTxt); expect(stat).toEqual({ ctimeMs: 1000000000001, @@ -224,7 +237,7 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => { it('fails to stat missing', async () => { const p = new MemPlugin(); - await assertAsyncError(p.stat('/bar.txt'), 'ENOENT'); + await assertAsyncError(p.stat(barTxt), 'ENOENT'); }); }); }); diff --git a/packages/insomnia-app/app/sync/git/__tests__/ne-db-plugin.test.js b/packages/insomnia-app/app/sync/git/__tests__/ne-db-plugin.test.js index d3c4e3d205..829b3a1944 100644 --- a/packages/insomnia-app/app/sync/git/__tests__/ne-db-plugin.test.js +++ b/packages/insomnia-app/app/sync/git/__tests__/ne-db-plugin.test.js @@ -30,56 +30,62 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => { describe('readdir()', () => { it('reads model IDs from model type folders', async () => { const pNeDB = new NeDBPlugin('wrk_1'); + const reqDir = path.join(GIT_INSOMNIA_DIR, models.request.type); + const wrkDir = path.join(GIT_INSOMNIA_DIR, models.workspace.type); expect(await pNeDB.readdir(GIT_CLONE_DIR)).toEqual([GIT_INSOMNIA_DIR_NAME]); expect(await pNeDB.readdir(GIT_INSOMNIA_DIR)).toEqual([ - 'ApiSpec', - 'Environment', - 'Request', - 'RequestGroup', - 'Workspace', + models.apiSpec.type, + models.environment.type, + models.request.type, + models.requestGroup.type, + models.workspace.type, ]); - expect(await pNeDB.readdir(`${GIT_INSOMNIA_DIR}/Request`)).toEqual([ - 'req_1.yml', - 'req_2.yml', - ]); - expect(await pNeDB.readdir(`${GIT_INSOMNIA_DIR}/Workspace`)).toEqual(['wrk_1.yml']); + + expect(await pNeDB.readdir(reqDir)).toEqual(['req_1.yml', 'req_2.yml']); + expect(await pNeDB.readdir(wrkDir)).toEqual(['wrk_1.yml']); }); }); describe('readFile()', () => { it('reads file from model/id folders', async () => { + const wrk1Yml = path.join(GIT_INSOMNIA_DIR, models.workspace.type, 'wrk_1.yml'); + const req1Yml = path.join(GIT_INSOMNIA_DIR, models.request.type, 'req_1.yml'); + const reqXYml = path.join(GIT_INSOMNIA_DIR, models.request.type, 'req_x.yml'); + const pNeDB = new NeDBPlugin('wrk_1'); - expect( - YAML.parse(await pNeDB.readFile(`${GIT_INSOMNIA_DIR}/Workspace/wrk_1.yml`, 'utf8')), - ).toEqual(expect.objectContaining({ _id: 'wrk_1', parentId: null })); + expect(YAML.parse(await pNeDB.readFile(wrk1Yml, 'utf8'))).toEqual( + expect.objectContaining({ _id: 'wrk_1', parentId: null }), + ); - expect( - YAML.parse(await pNeDB.readFile(`${GIT_INSOMNIA_DIR}/Request/req_1.yml`, 'utf8')), - ).toEqual(expect.objectContaining({ _id: 'req_1', parentId: 'wrk_1' })); + expect(YAML.parse(await pNeDB.readFile(req1Yml, 'utf8'))).toEqual( + expect.objectContaining({ _id: 'req_1', parentId: 'wrk_1' }), + ); - await assertAsyncError(pNeDB.readFile(`${GIT_INSOMNIA_DIR}/Request/req_x.yml`)); + await assertAsyncError(pNeDB.readFile(reqXYml)); }); }); describe('stat()', () => { it('stats a dir', async () => { + // Assemble + const reqDir = path.join(GIT_INSOMNIA_DIR, models.request.type); + const wrkDir = path.join(GIT_INSOMNIA_DIR, models.workspace.type); + + const dirType = expect.objectContaining({ type: 'dir' }); + const fileType = expect.objectContaining({ type: 'file' }); + + // Act const pNeDB = new NeDBPlugin('wrk_1'); - expect(await pNeDB.stat(GIT_CLONE_DIR)).toEqual(expect.objectContaining({ type: 'dir' })); - expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}`)).toEqual( - expect.objectContaining({ type: 'dir' }), - ); - expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}/Workspace/wrk_1.yml`)).toEqual( - expect.objectContaining({ type: 'file' }), - ); - expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}/Request`)).toEqual( - expect.objectContaining({ type: 'dir' }), - ); - expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}/Request/req_2.yml`)).toEqual( - expect.objectContaining({ type: 'file' }), - ); + // Assert + expect(await pNeDB.stat(GIT_CLONE_DIR)).toEqual(dirType); + expect(await pNeDB.stat(GIT_INSOMNIA_DIR)).toEqual(dirType); + expect(await pNeDB.stat(reqDir)).toEqual(dirType); + + expect(await pNeDB.stat(path.join(wrkDir, 'wrk_1.yml'))).toEqual(fileType); + expect(await pNeDB.stat(path.join(reqDir, 'req_2.yml'))).toEqual(fileType); }); }); @@ -90,8 +96,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => { const workspaceId = 'wrk_1'; const pNeDB = new NeDBPlugin(workspaceId); - const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId }; - const filePath = `anotherDir/${env.type}/${env._id}.yml`; + const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId }; + const filePath = path.join('anotherDir', env.type, `${env._id}.yml`); // Act await pNeDB.writeFile(filePath, YAML.stringify(env)); @@ -109,8 +115,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => { const pNeDB = new NeDBPlugin(workspaceId); const upsertSpy = jest.spyOn(db, 'upsert'); - const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId }; - const filePath = `${GIT_INSOMNIA_DIR}/${env.type}/${env._id}.yml`; + const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId }; + const filePath = path.join(GIT_INSOMNIA_DIR, env.type, `${env._id}.yml`); // Act await pNeDB.writeFile(filePath, YAML.stringify(env)); @@ -128,8 +134,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => { const workspaceId = 'wrk_1'; const pNeDB = new NeDBPlugin(workspaceId); - const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId }; - const filePath = `${GIT_INSOMNIA_DIR}/${env.type}/env_2.yml`; + const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId }; + const filePath = path.join(GIT_INSOMNIA_DIR, env.type, `env_2.yml`); // Act const promiseResult = pNeDB.writeFile(filePath, YAML.stringify(env)); @@ -145,8 +151,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => { const workspaceId = 'wrk_1'; const pNeDB = new NeDBPlugin(workspaceId); - const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId }; - const filePath = `${GIT_INSOMNIA_DIR}/Request/${env._id}.yml`; + const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId }; + const filePath = path.join(GIT_INSOMNIA_DIR, models.request.type, `${env._id}.yml`); // Act const promiseResult = pNeDB.writeFile(filePath, YAML.stringify(env)); @@ -165,7 +171,6 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => { const promiseResult = pNeDB.mkdir('', ''); - // Assert await expect(promiseResult).rejects.toThrowError('NeDBPlugin is not writable'); }); }); diff --git a/packages/insomnia-app/app/sync/git/__tests__/path-sep.test.js b/packages/insomnia-app/app/sync/git/__tests__/path-sep.test.js new file mode 100644 index 0000000000..5619c13562 --- /dev/null +++ b/packages/insomnia-app/app/sync/git/__tests__/path-sep.test.js @@ -0,0 +1,29 @@ +// @flow +import path from 'path'; +import { convertToOsSep, convertToPosixSep } from '../path-sep'; +jest.mock('path'); + +describe('convertToPosixSep()', () => { + it('should handle empty string', () => { + expect(convertToPosixSep('')).toBe(''); + }); + + it.each(['win32', 'posix'])('should convert separator from %s to posix', type => { + const input = path[type].join('a', 'b', 'c'); + const posix = path.posix.join('a', 'b', 'c'); + + expect(convertToPosixSep(input)).toBe(posix); + }); +}); + +describe.each(['win32', 'posix'])('convertToOsSep() where os is %s', osType => { + beforeAll(() => path.__mockPath(osType)); + afterAll(() => jest.restoreAllMocks()); + + it.each(['win32', 'posix'])(`should convert separators from %s to ${osType}`, inputType => { + const input = path[inputType].join('a', 'b', 'c'); + const output = path[osType].join('a', 'b', 'c'); + + expect(convertToOsSep(input)).toBe(output); + }); +}); diff --git a/packages/insomnia-app/app/sync/git/git-vcs.js b/packages/insomnia-app/app/sync/git/git-vcs.js index dd28252a52..1f4c210e71 100644 --- a/packages/insomnia-app/app/sync/git/git-vcs.js +++ b/packages/insomnia-app/app/sync/git/git-vcs.js @@ -2,6 +2,7 @@ import * as git from 'isomorphic-git'; import { trackEvent } from '../../common/analytics'; import { httpPlugin } from './http'; +import { convertToOsSep, convertToPosixSep } from './path-sep'; import path from 'path'; export type GitAuthor = {| @@ -97,7 +98,8 @@ export default class GitVCS { async listFiles(): Promise> { console.log('[git] List files'); - return git.listFiles({ ...this._baseOpts }); + const files = await git.listFiles({ ...this._baseOpts }); + return files.map(convertToOsSep); } async getBranch(): Promise { @@ -129,15 +131,23 @@ export default class GitVCS { } async status(filepath: string) { - return git.status({ ...this._baseOpts, filepath }); + return git.status({ + ...this._baseOpts, + filepath: convertToPosixSep(filepath), + }); } async add(relPath: string): Promise { + relPath = convertToPosixSep(relPath); console.log(`[git] Add ${relPath}`); - return git.add({ ...this._baseOpts, filepath: relPath }); + return git.add({ + ...this._baseOpts, + filepath: relPath, + }); } async remove(relPath: string): Promise { + relPath = convertToPosixSep(relPath); console.log(`[git] Remove relPath=${relPath}`); return git.remove({ ...this._baseOpts, filepath: relPath }); } @@ -312,7 +322,7 @@ export default class GitVCS { const obj = await git.readObject({ ...this._baseOpts, oid: treeOid, - filepath: objPath, + filepath: convertToPosixSep(objPath), encoding: 'utf8', }); diff --git a/packages/insomnia-app/app/sync/git/ne-db-plugin.js b/packages/insomnia-app/app/sync/git/ne-db-plugin.js index c6b5e80643..d143d2d360 100644 --- a/packages/insomnia-app/app/sync/git/ne-db-plugin.js +++ b/packages/insomnia-app/app/sync/git/ne-db-plugin.js @@ -172,7 +172,7 @@ export default class NeDBPlugin { type: 'file', mode: 0o777, size: fileBuff.length, - ino: doc._id, + ino: doc._id, // should be number instead of string https://nodejs.org/api/fs.html#fs_stats_ino I think flow should have detected this mtimeMs: doc.modified, }); } else { diff --git a/packages/insomnia-app/app/sync/git/path-sep.js b/packages/insomnia-app/app/sync/git/path-sep.js new file mode 100644 index 0000000000..9b962ccca3 --- /dev/null +++ b/packages/insomnia-app/app/sync/git/path-sep.js @@ -0,0 +1,19 @@ +// @flow +import path from 'path'; + +const win32SepRegex = /\\/g; +const posixSepRegex = /\//g; + +export function convertToPosixSep(filePath: string) { + return filePath.replace(win32SepRegex, path.posix.sep); +} + +export function convertToOsSep(filePath: string) { + // is windows, so convert posix sep to windows sep + if (path.sep === path.win32.sep) { + return filePath.replace(posixSepRegex, path.win32.sep); + } + + // is posix, so convert win32 sep to posix sep + return filePath.replace(win32SepRegex, path.posix.sep); +} diff --git a/packages/insomnia-app/app/ui/components/modals/git-staging-modal.js b/packages/insomnia-app/app/ui/components/modals/git-staging-modal.js index 4396586b64..79eea53d35 100644 --- a/packages/insomnia-app/app/ui/components/modals/git-staging-modal.js +++ b/packages/insomnia-app/app/ui/components/modals/git-staging-modal.js @@ -170,10 +170,9 @@ class GitStagingModal extends React.PureComponent { this.statusNames = {}; for (const doc of docs) { - this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.json`)] = - (doc: any).name || ''; - this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.yml`)] = - (doc: any).name || ''; + const name = (doc.type === models.apiSpec.type && doc.fileName) || doc.name || ''; + this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.json`)] = name; + this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.yml`)] = name; } // Create status items