From e49b3a4b9fc99bb392235b7cad36139faff08eec Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Fri, 30 Jul 2021 01:23:12 +1000 Subject: [PATCH] fix(server): correctly include projectRoot when adding a CI project from GUI (#17514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Barthélémy Ledoux Co-authored-by: semantic-release-bot Co-authored-by: Jennifer Shehane Co-authored-by: Chris Breiding --- npm/vite-dev-server/CHANGELOG.md | 7 ++++++ npm/vite-dev-server/cypress/styles.css | 3 +++ npm/vite-dev-server/cypress/support.js | 1 + npm/vite-dev-server/src/index.ts | 6 ++--- npm/vite-dev-server/src/makeCypressPlugin.ts | 13 ++++++---- npm/vite-dev-server/src/startServer.ts | 6 ++--- npm/vue/CHANGELOG.md | 7 ++++++ .../cypress/integration/setup_project_spec.js | 6 +++-- .../dashboard-projects-api.js | 4 ++-- packages/desktop-gui/src/runs/runs-list.jsx | 4 ++-- .../desktop-gui/src/runs/setup-project.jsx | 3 ++- packages/server/lib/gui/events.js | 4 ++-- packages/server/lib/project_static.ts | 1 + packages/server/test/unit/gui/events_spec.js | 24 +++++++++++++++++-- 14 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 npm/vite-dev-server/cypress/styles.css diff --git a/npm/vite-dev-server/CHANGELOG.md b/npm/vite-dev-server/CHANGELOG.md index d8a885c0723e..5990fb6b482f 100644 --- a/npm/vite-dev-server/CHANGELOG.md +++ b/npm/vite-dev-server/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vite-dev-server-v2.0.3](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.2...@cypress/vite-dev-server-v2.0.3) (2021-07-27) + + +### Bug Fixes + +* make vite re-run on supportFile change ([#17485](https://github.com/cypress-io/cypress/issues/17485)) ([6cbf4c3](https://github.com/cypress-io/cypress/commit/6cbf4c38296d6287fbcbb0ef5ecd21cf63606153)) + # [@cypress/vite-dev-server-v2.0.2](https://github.com/cypress-io/cypress/compare/@cypress/vite-dev-server-v2.0.1...@cypress/vite-dev-server-v2.0.2) (2021-07-15) diff --git a/npm/vite-dev-server/cypress/styles.css b/npm/vite-dev-server/cypress/styles.css new file mode 100644 index 000000000000..33768f9211ff --- /dev/null +++ b/npm/vite-dev-server/cypress/styles.css @@ -0,0 +1,3 @@ +body { + color: indigo; +} \ No newline at end of file diff --git a/npm/vite-dev-server/cypress/support.js b/npm/vite-dev-server/cypress/support.js index 18915a9458fc..192364e1f2b8 100644 --- a/npm/vite-dev-server/cypress/support.js +++ b/npm/vite-dev-server/cypress/support.js @@ -1,4 +1,5 @@ import '@testing-library/cypress/add-commands' +import './styles.css' before(() => { window.supportFileWasLoaded = true diff --git a/npm/vite-dev-server/src/index.ts b/npm/vite-dev-server/src/index.ts index 2d3a22978028..f5197353b5f7 100644 --- a/npm/vite-dev-server/src/index.ts +++ b/npm/vite-dev-server/src/index.ts @@ -1,8 +1,8 @@ import { debug as debugFn } from 'debug' -import { start as createDevServer, StartDevServer } from './startServer' +import { start as createDevServer, StartDevServerOptions } from './startServer' const debug = debugFn('cypress:vite-dev-server:vite') -export { StartDevServer } +export { StartDevServerOptions } type DoneCallback = () => unknown @@ -11,7 +11,7 @@ export interface ResolvedDevServerConfig { close: (done?: DoneCallback) => void } -export async function startDevServer (startDevServerArgs: StartDevServer): Promise { +export async function startDevServer (startDevServerArgs: StartDevServerOptions): Promise { const viteDevServer = await createDevServer(startDevServerArgs) const app = await viteDevServer.listen() diff --git a/npm/vite-dev-server/src/makeCypressPlugin.ts b/npm/vite-dev-server/src/makeCypressPlugin.ts index ff791dfd5c38..fc177ccbc912 100644 --- a/npm/vite-dev-server/src/makeCypressPlugin.ts +++ b/npm/vite-dev-server/src/makeCypressPlugin.ts @@ -21,8 +21,12 @@ const INIT_FILEPATH = resolve(__dirname, '../client/initCypressTests.js') const HMR_DEPENDENCY_LOOKUP_MAX_ITERATION = 50 -function getSpecsSet (specs: Spec[]) { - return new Set(specs.map((spec) => spec.absolute)) +function getSpecsPathsSet (specs: Spec[], supportFile?: string | null) { + return new Set( + supportFile + ? [...specs.map((spec) => spec.absolute), supportFile] + : specs.map((spec) => spec.absolute), + ) } interface Spec{ @@ -38,10 +42,10 @@ export const makeCypressPlugin = ( ): Plugin => { let base = '/' - let specsPathsSet = getSpecsSet(specs) + let specsPathsSet = getSpecsPathsSet(specs, supportFilePath) devServerEvents.on('dev-server:specs:changed', (specs: Spec[]) => { - specsPathsSet = getSpecsSet(specs) + specsPathsSet = getSpecsPathsSet(specs, supportFilePath) }) const posixSupportFilePath = supportFilePath ? convertPathToPosix(resolve(projectRoot, supportFilePath)) : undefined @@ -101,6 +105,7 @@ export const makeCypressPlugin = ( // as soon as we find one of the specs, we trigger the re-run of tests for (const mod of moduleImporters.values()) { + debug('handleHotUpdate - mod.file', mod.file) if (specsPathsSet.has(mod.file)) { debug('handleHotUpdate - compile success') devServerEvents.emit('dev-server:compile:success', { specFile: mod.file }) diff --git a/npm/vite-dev-server/src/startServer.ts b/npm/vite-dev-server/src/startServer.ts index b977fd98ec95..ab2468b8e854 100644 --- a/npm/vite-dev-server/src/startServer.ts +++ b/npm/vite-dev-server/src/startServer.ts @@ -13,7 +13,7 @@ interface Options { [key: string]: unknown } -export interface StartDevServer { +export interface StartDevServerOptions { /** * the Cypress options object */ @@ -27,7 +27,7 @@ export interface StartDevServer { viteConfig?: UserConfig } -const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Promise => { +const resolveServerConfig = async ({ viteConfig, options }: StartDevServerOptions): Promise => { const { projectRoot, supportFile } = options.config const requiredOptions: InlineConfig = { @@ -66,7 +66,7 @@ const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Pro return finalConfig } -export async function start (devServerOptions: StartDevServer): Promise { +export async function start (devServerOptions: StartDevServerOptions): Promise { if (!devServerOptions.viteConfig) { debug('User did not pass in any Vite dev server configuration') devServerOptions.viteConfig = {} diff --git a/npm/vue/CHANGELOG.md b/npm/vue/CHANGELOG.md index 54d3c19ebb5e..fe7df62caa44 100644 --- a/npm/vue/CHANGELOG.md +++ b/npm/vue/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@cypress/vue-v3.0.0-beta.4](https://github.com/cypress-io/cypress/compare/@cypress/vue-v3.0.0-beta.3...@cypress/vue-v3.0.0-beta.4) (2021-07-27) + + +### Bug Fixes + +* do not register CT specific event in e2e mode ([5836203](https://github.com/cypress-io/cypress/commit/58362037fd231c6fdc587e422fc139bf7546ac2d)) + # [@cypress/vue-v3.0.0-beta.3](https://github.com/cypress-io/cypress/compare/@cypress/vue-v3.0.0-beta.2...@cypress/vue-v3.0.0-beta.3) (2021-06-24) diff --git a/packages/desktop-gui/cypress/integration/setup_project_spec.js b/packages/desktop-gui/cypress/integration/setup_project_spec.js index 130513e72abd..bc1b5b534549 100644 --- a/packages/desktop-gui/cypress/integration/setup_project_spec.js +++ b/packages/desktop-gui/cypress/integration/setup_project_spec.js @@ -4,6 +4,7 @@ const onSubmitNewProject = function (orgId) { .contains('.btn', 'Set up project').click() .then(() => { expect(this.ipc.setupDashboardProject).to.be.calledWith({ + projectRoot: '/foo/bar', projectName: this.config.projectName, orgId, public: false, @@ -21,6 +22,7 @@ const onSubmitNewProject = function (orgId) { .then(() => { expect(this.ipc.setupDashboardProject).to.be.calledWith({ projectName: 'New Project', + projectRoot: '/foo/bar', orgId, public: true, }) @@ -114,7 +116,7 @@ describe('Connect to Dashboard', function () { cy.stub(this.ipc, 'getRecordKeys').resolves(this.keys) cy.stub(this.ipc, 'pingApiServer').resolves() cy.stub(this.ipc, 'externalOpen') - cy.stub(this.ipc, 'setProjectId').resolvesArg(0) + cy.stub(this.ipc, 'setProjectId').callsFake((arg) => Promise.resolve(arg.id)) cy.stub(this.ipc, 'beginAuth').resolves() this.getCurrentUser = this.util.deferred() @@ -485,7 +487,7 @@ describe('Connect to Dashboard', function () { cy.get('.setup-project') .contains('.btn', 'Set up project').click() .then(() => { - expect(this.ipc.setProjectId).to.be.calledWith(this.dashboardProjects[1].id) + expect(this.ipc.setProjectId).to.be.calledWith({ id: this.dashboardProjects[1].id, projectRoot: '/foo/bar' }) }) }) diff --git a/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js b/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js index d437739d819b..42d6534ec190 100644 --- a/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js +++ b/packages/desktop-gui/src/dashboard-projects/dashboard-projects-api.js @@ -45,8 +45,8 @@ const setupDashboardProject = (projectDetails) => { .catch(ipc.isUnauthed, ipc.handleUnauthed) } -const setProjectId = (id) => { - return ipc.setProjectId(id) +const setProjectId = (id, projectRoot) => { + return ipc.setProjectId({ id, projectRoot }) } export default { diff --git a/packages/desktop-gui/src/runs/runs-list.jsx b/packages/desktop-gui/src/runs/runs-list.jsx index 13bb56636ae3..f353d24242a9 100644 --- a/packages/desktop-gui/src/runs/runs-list.jsx +++ b/packages/desktop-gui/src/runs/runs-list.jsx @@ -108,8 +108,8 @@ class RunsList extends Component { _getRecordKeys () { if (this._needsKey()) { - projectsApi.getRecordKeys().then((keys = []) => { - if (keys.length) { + projectsApi.getRecordKeys().then((keys) => { + if (keys && keys.length) { this.setState({ recordKey: keys[0].id }) } }) diff --git a/packages/desktop-gui/src/runs/setup-project.jsx b/packages/desktop-gui/src/runs/setup-project.jsx index c5f5f5744529..3f9db844f857 100644 --- a/packages/desktop-gui/src/runs/setup-project.jsx +++ b/packages/desktop-gui/src/runs/setup-project.jsx @@ -375,12 +375,13 @@ class SetupProject extends Component { if (this.state.newProject) { return dashboardProjectsApi.setupDashboardProject({ projectName: this.state.projectName, + projectRoot: this.props.project.path, orgId: this.state.selectedOrgId, public: this.state.public, }) } - return dashboardProjectsApi.setProjectId(this.state.selectedProjectId) + return dashboardProjectsApi.setProjectId(this.state.selectedProjectId, this.props.project.path) .then((id) => { const project = dashboardProjectsStore.getProjectById(id) diff --git a/packages/server/lib/gui/events.js b/packages/server/lib/gui/events.js index f8e2b7eb814f..636f2f0cfc8f 100644 --- a/packages/server/lib/gui/events.js +++ b/packages/server/lib/gui/events.js @@ -332,12 +332,12 @@ const handleEvent = function (options, bus, event, id, type, arg) { .catch(sendErr) case 'setup:dashboard:project': - return ProjectStatic.createCiProject(arg, options.projectRoot) + return ProjectStatic.createCiProject(arg, arg.projectRoot) .then(send) .catch(sendErr) case 'set:project:id': - return ProjectStatic.writeProjectId(arg, options.projectRoot) + return ProjectStatic.writeProjectId(arg.id, arg.projectRoot) .then(send) .catch(sendErr) diff --git a/packages/server/lib/project_static.ts b/packages/server/lib/project_static.ts index 10dde6ce9b18..4768d913a303 100644 --- a/packages/server/lib/project_static.ts +++ b/packages/server/lib/project_static.ts @@ -177,6 +177,7 @@ export async function writeProjectId (id: string, projectRoot: string) { interface ProjectDetails { projectName: string + projectRoot: string orgId: string | null public: boolean } diff --git a/packages/server/test/unit/gui/events_spec.js b/packages/server/test/unit/gui/events_spec.js index 6d8a80e2dece..9c469be9136e 100644 --- a/packages/server/test/unit/gui/events_spec.js +++ b/packages/server/test/unit/gui/events_spec.js @@ -923,9 +923,28 @@ describe('lib/gui/events', () => { }) }) + describe('set:project:id', () => { + it('calls writeProjectId with projectRoot', function () { + const arg = { id: '1', projectRoot: '/project/root/' } + const stub = sinon.stub(ProjectStatic, 'writeProjectId').resolves() + + return this.handleEvent('set:project:id', arg) + .then(() => { + expect(stub).to.be.calledWith(arg.id, arg.projectRoot) + expect(this.send.firstCall.args[0]).to.eq('response') + expect(this.send.firstCall.args[1].id).to.match(/set:project:id-/) + }) + }) + }) + describe('setup:dashboard:project', () => { it('returns result of ProjectStatic.createCiProject', function () { - return this.handleEvent('setup:dashboard:project').then((assert) => { + const arg = { projectRoot: '/project/root/' } + const stub = sinon.stub(ProjectStatic, 'createCiProject').resolves() + + return this.handleEvent('setup:dashboard:project', arg) + .then(() => { + expect(stub).to.be.calledWith(arg, arg.projectRoot) expect(this.send.firstCall.args[0]).to.eq('response') expect(this.send.firstCall.args[1].id).to.match(/setup:dashboard:project-/) }) @@ -936,7 +955,8 @@ describe('lib/gui/events', () => { sinon.stub(ProjectStatic, 'createCiProject').rejects(err) - return this.handleEvent('setup:dashboard:project').then((assert) => { + return this.handleEvent('setup:dashboard:project', { projectRoot: '/foo/bar' }) + .then((assert) => { return assert.sendErrCalledWith(err) }) })