UNPKG

@teambit/lanes

Version:
624 lines (613 loc) • 25.3 kB
"use strict"; function _chai() { const data = require("chai"); _chai = function () { return data; }; return data; } function _fsExtra() { const data = _interopRequireDefault(require("fs-extra")); _fsExtra = function () { return data; }; return data; } function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _harmonyTesting() { const data = require("@teambit/harmony.testing.load-aspect"); _harmonyTesting = function () { return data; }; return data; } function _remove() { const data = require("@teambit/remove"); _remove = function () { return data; }; return data; } function _snapping() { const data = require("@teambit/snapping"); _snapping = function () { return data; }; return data; } function _workspace() { const data = require("@teambit/workspace"); _workspace = function () { return data; }; return data; } function _export() { const data = require("@teambit/export"); _export = function () { return data; }; return data; } function _workspaceTesting() { const data = require("@teambit/workspace.testing.mock-workspace"); _workspaceTesting = function () { return data; }; return data; } function _componentTesting() { const data = require("@teambit/component.testing.mock-components"); _componentTesting = function () { return data; }; return data; } function _lanesEntities() { const data = require("@teambit/lanes.entities.lane-diff"); _lanesEntities = function () { return data; }; return data; } function _lanes() { const data = require("./lanes.aspect"); _lanes = function () { return data; }; return data; } function _mergeLanes() { const data = require("@teambit/merge-lanes"); _mergeLanes = function () { return data; }; return data; } function _graphql() { const data = require("@teambit/graphql"); _graphql = function () { return data; }; return data; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } describe('LanesAspect', function () { this.timeout(0); describe('getLanes()', () => { let lanes; let workspaceData; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, workspacePath); await lanes.createLane('stage'); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should list all lanes', async () => { const currentLanes = await lanes.getLanes({}); (0, _chai().expect)(currentLanes).to.have.lengthOf(1); (0, _chai().expect)(currentLanes[0].name).to.equal('stage'); }); }); describe('isLaneUpToDate', () => { let lanes; let snapping; let workspaceData; let harmony; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); harmony = await (0, _harmonyTesting().loadManyAspects)([_snapping().SnappingAspect, _export().ExportAspect, _lanes().LanesAspect, _workspace().WorkspaceAspect], workspacePath); snapping = harmony.get(_snapping().SnappingAspect.id); await snapping.tag({ ids: ['comp1'], build: false, ignoreIssues: 'MissingManuallyConfiguredPackages' }); const exporter = harmony.get(_export().ExportAspect.id); await exporter.export(); lanes = harmony.get(_lanes().LanesAspect.id); await lanes.createLane('stage'); await (0, _componentTesting().modifyMockedComponents)(workspacePath, 'v2'); const result = await snapping.snap({ pattern: 'comp1', build: false, ignoreIssues: 'MissingManuallyConfiguredPackages' }); // intermediate step, make sure it is snapped (0, _chai().expect)(result?.snappedComponents.length).to.equal(1); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should return that the lane is up to date when the lane is ahead of main', async () => { const currentLane = await lanes.getCurrentLane(); if (!currentLane) throw new Error('unable to get the current lane'); const isUpToDate = (await lanes.diffStatus(currentLane.toLaneId(), undefined, { skipChanges: true })).componentsStatus.every(c => c.upToDate); (0, _chai().expect)(isUpToDate).to.be.true; }); it('should return that the lane is not up to date when main is ahead', async () => { const currentLane = await lanes.getCurrentLane(); if (!currentLane) throw new Error('unable to get the current lane'); await lanes.switchLanes('main', { skipDependencyInstallation: true }); await snapping.snap({ pattern: 'comp1', build: false, unmodified: true, ignoreIssues: 'MissingManuallyConfiguredPackages' }); const isUpToDate = (await lanes.diffStatus(currentLane.toLaneId(), undefined, { skipChanges: true })).componentsStatus.every(c => c.upToDate); (0, _chai().expect)(isUpToDate).to.be.false; }); }); describe('laneDiff', () => { let harmony; let lanes; let snapping; let workspaceData; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); harmony = await (0, _harmonyTesting().loadManyAspects)([_snapping().SnappingAspect, _export().ExportAspect, _lanes().LanesAspect, _workspace().WorkspaceAspect], workspacePath); snapping = harmony.get(_snapping().SnappingAspect.id); await snapping.tag({ ids: ['comp1'], build: false }); const exporter = harmony.get(_export().ExportAspect.id); await exporter.export(); lanes = harmony.get(_lanes().LanesAspect.id); await lanes.createLane('stage'); const result = await snapping.snap({ pattern: 'comp1', build: false, unmodified: true }); // intermediate step, make sure it is snapped (0, _chai().expect)(result?.snappedComponents.length).to.equal(1); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should return that the lane is up to date when the lane is ahead of main', async () => { const currentLane = await lanes.getCurrentLane(); if (!currentLane) throw new Error('unable to get the current lane'); const laneDiffResults = await lanes.diffStatus(currentLane.toLaneId()); (0, _chai().expect)(laneDiffResults.componentsStatus[0].upToDate).to.be.true; (0, _chai().expect)(laneDiffResults.componentsStatus[0].changeType).to.equal(_lanesEntities().ChangeType.NONE); }); it('should return that the lane is not up to date when main is ahead', async () => { const currentLane = await lanes.getCurrentLane(); if (!currentLane) throw new Error('unable to get the current lane'); await lanes.switchLanes('main', { skipDependencyInstallation: true }); await snapping.snap({ pattern: 'comp1', build: false, unmodified: true }); const laneDiffResults = await lanes.diffStatus(currentLane.toLaneId()); (0, _chai().expect)(laneDiffResults.componentsStatus[0].upToDate).to.be.false; (0, _chai().expect)(laneDiffResults.componentsStatus[0].changeType).to.equal(_lanesEntities().ChangeType.NONE); }); }); describe('restoreLane()', () => { let lanes; let workspaceData; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, workspacePath); await lanes.createLane('stage'); // as an intermediate step, make sure the lane was created const currentLanes = await lanes.getLanes({}); (0, _chai().expect)(currentLanes).to.have.lengthOf(1); await lanes.switchLanes('main', { skipDependencyInstallation: true }); await lanes.removeLanes(['stage']); // as an intermediate step, make sure the lane was removed const lanesAfterDelete = await lanes.getLanes({}); (0, _chai().expect)(lanesAfterDelete).to.have.lengthOf(0); await lanes.restoreLane(currentLanes[0].hash); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should restore the deleted lane', async () => { const currentLanes = await lanes.getLanes({}); (0, _chai().expect)(currentLanes).to.have.lengthOf(1); (0, _chai().expect)(currentLanes[0].id.name).to.equal('stage'); }); describe('delete restored lane', () => { let output; before(async () => { output = await lanes.removeLanes(['stage']); }); it('should not throw', () => { (0, _chai().expect)(output).to.have.lengthOf(1); }); }); }); describe('restore lane when an existing lane has the same id', () => { let lanes; let workspaceData; let laneHash; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, workspacePath); await lanes.createLane('stage'); // as an intermediate step, make sure the lane was created const currentLanes = await lanes.getLanes({}); (0, _chai().expect)(currentLanes).to.have.lengthOf(1); await lanes.switchLanes('main', { skipDependencyInstallation: true }); await lanes.removeLanes(['stage']); await lanes.createLane('stage'); laneHash = currentLanes[0].hash; }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should throw when restoring the lane', async () => { let error; try { await lanes.restoreLane(laneHash); } catch (err) { error = err; } (0, _chai().expect)(error).to.be.instanceOf(Error); (0, _chai().expect)(error?.message).to.include('unable to restore lane'); }); }); describe('lane history', () => { let lanes; let workspaceData; let snapping; let laneId; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, workspacePath); await lanes.createLane('stage'); snapping = await (0, _harmonyTesting().loadAspect)(_snapping().SnappingAspect, workspacePath); const currentLaneId = lanes.getCurrentLaneId(); if (!currentLaneId) throw new Error('unable to get the current lane-id'); laneId = currentLaneId; }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should create lane history object when creating a new lane', async () => { const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); (0, _chai().expect)(Object.keys(history).length).to.equal(1); }); describe('snapping', () => { let snappingResult; before(async () => { snappingResult = await snapping.snap({ pattern: 'comp1', build: false, message: 'first snap' }); }); it('should add a record to LaneHistory when snapping', async () => { const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); (0, _chai().expect)(Object.keys(history).length).to.equal(2); const snapHistory = history[Object.keys(history)[1]]; (0, _chai().expect)(snapHistory.log.message).to.equal('snap (first snap)'); (0, _chai().expect)(snapHistory.components.length).to.equal(1); (0, _chai().expect)(snapHistory.components[0]).to.equal(snappingResult?.snappedComponents[0].id.toString()); }); describe('snap again and export', () => { let exportResults; before(async () => { const compFile = _path().default.join(workspaceData.workspacePath, 'comp1/index.js'); await _fsExtra().default.appendFile(compFile, `\nconsole.log('second-snap');`); // make another snap to check to test the checkout later. await snapping.snap({ pattern: 'comp1', build: false, message: 'second snap' }); const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); (0, _chai().expect)(Object.keys(history).length).to.equal(3); const exporter = await (0, _harmonyTesting().loadAspect)(_export().ExportAspect, workspaceData.workspacePath); exportResults = await exporter.export(); }); it('should export successfully', () => { (0, _chai().expect)(exportResults.componentsIds.length).to.equal(1); (0, _chai().expect)(exportResults.exportedLanes.length).to.equal(1); }); describe('import to another workspace', () => { let newWorkspace; before(async () => { newWorkspace = (0, _workspaceTesting().mockWorkspace)({ bareScopeName: workspaceData.remoteScopeName }); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, newWorkspace.workspacePath); await lanes.switchLanes(laneId.toString(), { skipDependencyInstallation: true }); await lanes.importLaneObject(laneId, true, true); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(newWorkspace); }); it('should not add a record to the lane-history', async () => { const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); (0, _chai().expect)(Object.keys(history).length).to.equal(3); }); it('should be able to checkout to a previous state of the lane', async () => { const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); const snapHistoryId = Object.keys(history).find(key => history[key].log.message?.includes('first snap')); if (!snapHistoryId) throw new Error('unable to find snap history of the first snap'); const results = await lanes.checkoutHistory(snapHistoryId, { skipDependencyInstallation: true }); (0, _chai().expect)(results.components?.length).to.equal(1); (0, _chai().expect)(results.failedComponents?.length).to.equal(0); }); it('should be able to revert to a previous history id', async () => { const revertWorkspace = (0, _workspaceTesting().mockWorkspace)({ bareScopeName: workspaceData.remoteScopeName }); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, revertWorkspace.workspacePath); await lanes.switchLanes(laneId.toString(), { skipDependencyInstallation: true }); await lanes.importLaneObject(laneId, true, true); const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); const snapHistoryId = Object.keys(history).find(key => history[key].log.message?.includes('first snap')); if (!snapHistoryId) throw new Error('unable to find snap history of the first snap'); const results = await lanes.revertHistory(snapHistoryId, { skipDependencyInstallation: true }); (0, _chai().expect)(results.components?.length).to.equal(1); (0, _chai().expect)(results.failedComponents?.length).to.equal(0); const compFile = _path().default.join(revertWorkspace.workspacePath, revertWorkspace.remoteScopeName, 'comp1/index.js'); const compFileContent = await _fsExtra().default.readFile(compFile, 'utf8'); // make sure it reverts to the first snap. (0, _chai().expect)(compFileContent).to.not.include('second-snap'); // make sure it keeps the version in .bitmap intact and doesn't change it to the first snap. (as with checkout) const secondSnapHistoryId = Object.keys(history).find(key => history[key].log.message?.includes('second snap')); if (!secondSnapHistoryId) throw new Error('unable to find snap history of the second snap'); const secondSnapHistory = history[secondSnapHistoryId]; const workspace = await (0, _harmonyTesting().loadAspect)(_workspace().WorkspaceAspect, revertWorkspace.workspacePath); const ids = await workspace.listIds(); (0, _chai().expect)(ids[0].toString()).to.equal(secondSnapHistory.components[0]); await (0, _workspaceTesting().destroyWorkspace)(revertWorkspace); }); }); }); }); }); describe('create lanes with the same name different scope', () => { let lanes; let workspaceData; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); lanes = await (0, _harmonyTesting().loadAspect)(_lanes().LanesAspect, workspacePath); await lanes.createLane('stage'); await lanes.switchLanes('main', { skipDependencyInstallation: true }); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should not throw when creating the second lane', async () => { await lanes.createLane('stage', { scope: 'new-scope' }); const currentLanes = await lanes.getLanes({}); (0, _chai().expect)(currentLanes.length).to.equal(2); (0, _chai().expect)(currentLanes[0].id.name).to.equal('stage'); (0, _chai().expect)(currentLanes[1].id.name).to.equal('stage'); }); }); // todo: fix after deleting teambit.legacy // for some reason it is trying to add the core-aspect teambit.component/remove to the graph and then // it complains that it has no version. from the cli it doesn't happen. describe.skip('delete component on a lane after export', () => { let lanes; let workspaceData; let snapping; let laneId; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); const harmony = await (0, _harmonyTesting().loadManyAspects)([_snapping().SnappingAspect, _export().ExportAspect, _remove().RemoveAspect, _workspace().WorkspaceAspect, _lanes().LanesAspect], workspaceData.workspacePath); lanes = harmony.get(_lanes().LanesAspect.id); await lanes.createLane('stage'); const currentLaneId = lanes.getCurrentLaneId(); if (!currentLaneId) throw new Error('unable to get the current lane-id'); laneId = currentLaneId; snapping = harmony.get(_snapping().SnappingAspect.id); await snapping.snap({ build: false }); const exporter = harmony.get(_export().ExportAspect.id); await exporter.export(); const remove = harmony.get(_remove().RemoveAspect.id); await remove.deleteComps('comp1'); await snapping.snap({ build: false }); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should save the deleted data into the lane object', async () => { const lane = await lanes.getCurrentLane(); (0, _chai().expect)(lane?.components[0].isDeleted).to.be.true; }); it('should save the deleted data into lane history', async () => { const laneHistory = await lanes.getLaneHistory(laneId); const history = laneHistory.getHistory(); (0, _chai().expect)(Object.keys(history).length).to.equal(3); const snapHistory = history[Object.keys(history)[2]]; (0, _chai().expect)(snapHistory.deleted?.length).to.equal(1); }); }); describe('create comps on a lane then switch to main with --head', () => { let lanes; let workspaceData; let snapping; let laneId; let harmony; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; await (0, _componentTesting().mockComponents)(workspacePath); harmony = await (0, _harmonyTesting().loadManyAspects)([_snapping().SnappingAspect, _export().ExportAspect, _remove().RemoveAspect, _workspace().WorkspaceAspect, _lanes().LanesAspect], workspaceData.workspacePath); lanes = harmony.get(_lanes().LanesAspect.id); await lanes.createLane('stage'); const currentLaneId = lanes.getCurrentLaneId(); if (!currentLaneId) throw new Error('unable to get the current lane-id'); laneId = currentLaneId; snapping = harmony.get(_snapping().SnappingAspect.id); await snapping.snap({ build: false }); const exporter = harmony.get(_export().ExportAspect.id); await exporter.export(); // in another workspace, merge the lane into main. const workspaceData2 = (0, _workspaceTesting().mockWorkspace)({ bareScopeName: workspaceData.remoteScopeName }); const harmony2 = await (0, _harmonyTesting().loadManyAspects)([_snapping().SnappingAspect, _export().ExportAspect, _remove().RemoveAspect, _workspace().WorkspaceAspect, _lanes().LanesAspect, _mergeLanes().MergeLanesAspect], workspaceData2.workspacePath); const mergeLanes2 = harmony2.get(_mergeLanes().MergeLanesAspect.id); const lanes2 = harmony2.get(_lanes().LanesAspect.id); const currentLaneId2 = lanes2.getCurrentLaneId(); await mergeLanes2.mergeLane(laneId, currentLaneId2, { mergeStrategy: 'manual', skipDependencyInstallation: true }); const export2 = harmony2.get(_export().ExportAspect.id); await export2.export(); // reload harmony, otherwise, the "lanes" aspect has the workspace of harmony2. harmony = await (0, _harmonyTesting().loadManyAspects)([_lanes().LanesAspect], workspaceData.workspacePath); lanes = harmony.get(_lanes().LanesAspect.id); await lanes.switchLanes('main', { head: true, skipDependencyInstallation: true }); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('the components should be available on main', () => { const workspace = harmony.get(_workspace().WorkspaceAspect.id); const ids = workspace.listIds(); (0, _chai().expect)(ids.length).to.equal(1); }); }); }); /** * TODO: this should not be here. It belongs to the GraphQL aspect. * The reason it was moved here is that otherwise, it forms circular dependencies. * we should think of a better way to handle this. */ describe('GraphQL Aspect', function () { this.timeout(0); describe('getSchemas and getSchema APIs', () => { let graphql; let workspaceData; before(async () => { workspaceData = (0, _workspaceTesting().mockWorkspace)(); const { workspacePath } = workspaceData; const harmony = await (0, _harmonyTesting().loadManyAspects)([_workspace().WorkspaceAspect, _graphql().GraphqlAspect, _lanes().LanesAspect], workspacePath); graphql = harmony.get(_graphql().GraphqlAspect.id); }); after(async () => { await (0, _workspaceTesting().destroyWorkspace)(workspaceData); }); it('should bring the schemas when calling getSchemas API', async () => { const schemas = graphql.getSchemas([_lanes().LanesAspect.id]); (0, _chai().expect)(schemas).to.be.an('array'); (0, _chai().expect)(schemas).to.have.lengthOf(1); (0, _chai().expect)(schemas[0]).to.be.an('object'); (0, _chai().expect)(schemas[0]).to.not.be.an('function'); }); it('should bring the schemas when calling getSchema API', async () => { const schema = graphql.getSchema(_lanes().LanesAspect.id); (0, _chai().expect)(schema).to.be.an('object'); (0, _chai().expect)(schema).to.not.be.an('function'); }); }); }); //# sourceMappingURL=lanes.spec.js.map