Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Angular CT Schematic #24374

Merged
merged 35 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c750eea
Merge pull request #23628 from cypress-io/develop
mike-plummer Aug 30, 2022
da0705f
chore: release @cypress/angular-v1.1.0
semantic-release-bot Aug 30, 2022
75da5c7
chore: release @cypress/schematic-v2.1.0
semantic-release-bot Aug 30, 2022
962322a
chore: release @cypress/mount-utils-v2.1.0
semantic-release-bot Aug 30, 2022
e581253
chore: release @cypress/react-v6.2.0
semantic-release-bot Aug 30, 2022
8bfcf38
chore: release @cypress/react18-v1.1.0
semantic-release-bot Aug 30, 2022
03a79d3
chore: release @cypress/svelte-v1.0.0
semantic-release-bot Aug 30, 2022
c55b0c2
chore: release @cypress/vue-v4.2.0
semantic-release-bot Aug 30, 2022
d519375
chore: release @cypress/vue2-v1.1.0
semantic-release-bot Aug 30, 2022
66e3d7c
chore: release @cypress/webpack-dev-server-v2.3.0
semantic-release-bot Aug 30, 2022
3fd56bc
fix(cypress-schematic): suffix template files so they are not ignored…
ZachJW34 Aug 31, 2022
2ce0792
chore: release @cypress/schematic-v2.1.1
semantic-release-bot Aug 31, 2022
f1a0794
fix: Use tsconfig from build if exists (closes #23673) (#23696)
yusijs Sep 13, 2022
af415e0
Merge pull request #23818 from cypress-io/develop
emilyrohrbough Sep 13, 2022
058cf22
feat: add support for generating angular component
w0wka91 Oct 21, 2022
60e4ada
feat: skip default test generation
w0wka91 Oct 23, 2022
91af0c9
feat: generate ct tests only if component was generated
w0wka91 Oct 23, 2022
5537c82
feat: add @cypress/schematic to schematicCollections
w0wka91 Oct 24, 2022
a82f793
feat: add documentation
w0wka91 Oct 24, 2022
7beb9f1
docs: document component generation
w0wka91 Oct 25, 2022
dffdd34
add test
w0wka91 Oct 28, 2022
4e8d7d1
Merge branch 'develop' into issue-22976
jordanpowell88 Oct 31, 2022
76606cd
Merge branch 'develop' into issue-22976
jordanpowell88 Nov 1, 2022
51f28a5
Merge branch 'develop' into issue-22976
jordanpowell88 Nov 14, 2022
cd3b253
Merge branch 'develop' into issue-22976
marktnoonan Nov 15, 2022
dd2cf7a
fix generate from component with dir
ZachJW34 Nov 22, 2022
1d40c3f
Merge branch 'develop' into issue-22976
ZachJW34 Nov 22, 2022
4fb5b57
fix CI
astone123 Nov 22, 2022
1c93b03
add variable to job defaults
astone123 Nov 22, 2022
d9fe5ef
merge in develop
lmiller1990 Nov 22, 2022
36d41db
Merge branch 'develop' into issue-22976
jordanpowell88 Nov 30, 2022
c3f2d2a
Merge branch 'develop' into issue-22976
jordanpowell88 Dec 6, 2022
4ab75a6
Merge branch 'develop' into issue-22976
Dec 8, 2022
a3c3e6f
remove v13 support
ZachJW34 Jan 23, 2023
97401f5
Merge branch 'develop' into issue-22976
ZachJW34 Jan 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions npm/cypress-schematic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ To install the schematic via cli arguments (installs both e2e and component test
ng add @cypress/schematic --e2e --component
```

The installation will add this schematic to the [default schematic collections](https://angular.io/guide/workspace-config#angular-cli-configuration-options). This allows you to execute the CLI commands without prefixing them with the package name.

To run Cypress in `open` mode within your project:

```shell script
Expand Down Expand Up @@ -78,37 +80,43 @@ ng run {project-name}:ct
To generate a new e2e spec file:

```shell script
ng generate @cypress/schematic:spec
ng generate spec
```

or (without cli prompt)

```shell script
ng generate @cypress/schematic:spec {name}
ng generate spec {name}
```

To generate a new component spec file:

```shell script
ng generate @cypress/schematic:spec --component
ng generate spec --component
```

or (without cli prompt)

```shell script
ng generate @cypress/schematic:spec {component name} --component
ng generate spec {component name} --component
```

To generate a new component spec file in a specific folder:

```shell script
ng generate @cypress/schematic:spec {component name} --component --path {path relative to project root}
ng generate spec {component name} --component --path {path relative to project root}
```

To generate new component spec files alongside all component files in a project:

```shell script
ng generate @cypress/schematic:specs-ct
ng generate specs-ct
```

To generate a new, generic component definition with a component spec file in the given or default project. This wraps the [Angular CLI Component Generator](https://angular.io/cli/generate#component) and supports the same arguments.

```shell script
ng generate component {component name}
```

## Builder Options 🛠
Expand Down
8 changes: 8 additions & 0 deletions npm/cypress-schematic/src/schematics/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
"description": "Create spec files for all Angular components in a project",
"factory": "./ng-generate/cypress-ct-tests/index",
"schema": "./ng-generate/cypress-ct-tests/schema.json"
},
"component": {
"description": "Creates a new, generic component definition in the given or default project.",
"aliases": [
"c"
],
"factory": "./ng-generate/component/index",
"schema": "./ng-generate/component/schema.json"
}
}
}
37 changes: 37 additions & 0 deletions npm/cypress-schematic/src/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'
import { join } from 'path'
import { expect } from 'chai'
import { JsonObject } from '@angular-devkit/core'

describe('@cypress/schematic: ng-add', () => {
const schematicRunner = new SchematicTestRunner(
Expand All @@ -16,6 +17,7 @@ describe('@cypress/schematic: ng-add', () => {
name: 'workspace',
newProjectRoot: 'projects',
version: '6.0.0',
packageManager: 'yarn',
}

const appOptions = {
Expand All @@ -26,6 +28,10 @@ describe('@cypress/schematic: ng-add', () => {
skipPackageJson: false,
}

const readAngularJson = (tree: UnitTestTree) => {
return tree.readJson('/angular.json') as JsonObject
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick q, it is a reasonable assumption that angular.json exists in this location? I made a new project with Nx using Angular and they put Cypress tests in a separate project directory to the main App, meaning angular.json might be somewhere else.

cc @jordanpowell88, I think we talked about something similar to this before

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lmiller1990 This generator is for angular CLI projects (which all have an angular.json file). In your Nx example they already have this functionality

}

beforeEach(async () => {
appTree = await schematicRunner.runExternalSchematicAsync('@schematics/angular', 'workspace', workspaceOptions).toPromise()
appTree = await schematicRunner.runExternalSchematicAsync('@schematics/angular', 'application', appOptions, appTree).toPromise()
Expand Down Expand Up @@ -58,4 +64,35 @@ describe('@cypress/schematic: ng-add', () => {
expect(files).to.contain('/projects/sandbox/cypress/fixtures/example.json')
})
})

it('should add @cypress/schematic to the schemaCollections array', async () => {
const tree = await schematicRunner.runSchematicAsync('ng-add', { 'component': true }, appTree).toPromise()
const angularJson = readAngularJson(tree)
const cliOptions = angularJson.cli as JsonObject

expect(cliOptions).to.eql({
packageManager: 'yarn',
schematicCollections: ['@cypress/schematic', '@schematics/angular'],
})
})

it('should not overwrite existing schemaCollections array', async () => {
let angularJson = readAngularJson(appTree)

appTree.overwrite('./angular.json', JSON.stringify({
...angularJson,
cli: {
schematicCollections: ['@any/schematic'],
},
}))

const tree = await schematicRunner.runSchematicAsync('ng-add', { 'component': true }, appTree).toPromise()

angularJson = readAngularJson(tree)
const cliOptions = angularJson.cli as JsonObject

expect(cliOptions).to.eql({
schematicCollections: ['@cypress/schematic', '@any/schematic', '@schematics/angular'],
})
})
})
28 changes: 28 additions & 0 deletions npm/cypress-schematic/src/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default function (_options: any): Rule {
addCtSpecs(_options),
addCypressTestScriptsToPackageJson(),
modifyAngularJson(_options),
addDefaultSchematic(),
])(tree, _context)
}
}
Expand Down Expand Up @@ -306,6 +307,33 @@ function modifyAngularJson (options: any): Rule {
}
}

function addDefaultSchematic (): Rule {
return (tree: Tree, _: SchematicContext) => {
if (tree.exists('./angular.json')) {
const angularJsonVal = getAngularJsonValue(tree)
const angularSchematic = '@schematics/angular'
const cli = {
...angularJsonVal.cli,
schematicCollections: ['@cypress/schematic', ...angularJsonVal?.cli?.schematicCollections ?? []],
}

if (cli.schematicCollections.indexOf('@schematics/angular') === -1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

schematicCollections is only for Angular-14 apps. Previously, the value was defaultCollection but it isn't an array. Should we override the default value instead for Angular 13 apps?

cli.schematicCollections.push(angularSchematic)
}

return tree.overwrite(
'./angular.json',
JSON.stringify({
...angularJsonVal,
cli,
}, null, 2),
)
}

throw new SchematicsException('angular.json not found')
}
}

export const getCypressConfigFile = (angularJsonVal: any, projectName: string) => {
const project = angularJsonVal.projects[projectName]
const tsConfig = project?.architect?.lint?.options?.tsConfig
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'
import { expect } from 'chai'
import { join } from 'path'

describe('ng-generate @cypress/schematic:component', () => {
const schematicRunner = new SchematicTestRunner(
'schematics',
join(__dirname, '../../collection.json'),
)
let appTree: UnitTestTree

const workspaceOptions = {
name: 'workspace',
newProjectRoot: 'projects',
version: '12.0.0',
}

const appOptions: Parameters<typeof schematicRunner['runExternalSchematicAsync']>[2] = {
name: 'sandbox',
inlineTemplate: false,
routing: false,
skipTests: false,
skipPackageJson: false,
}

beforeEach(async () => {
appTree = await schematicRunner.runExternalSchematicAsync('@schematics/angular', 'workspace', workspaceOptions).toPromise()
appTree = await schematicRunner.runExternalSchematicAsync('@schematics/angular', 'application', appOptions, appTree).toPromise()
})

it('should create cypress ct alongside the generated component', async () => {
const tree = await schematicRunner.runSchematicAsync('component', { name: 'foo', project: 'sandbox' }, appTree).toPromise()

expect(tree.files).to.contain('/projects/sandbox/src/app/foo/foo.component.ts')
expect(tree.files).to.contain('/projects/sandbox/src/app/foo/foo.component.html')
expect(tree.files).to.contain('/projects/sandbox/src/app/foo/foo.component.cy.ts')
expect(tree.files).to.contain('/projects/sandbox/src/app/foo/foo.component.css')
expect(tree.files).not.to.contain('/projects/sandbox/src/app/foo/foo.component.spec.ts')
})

it('should not generate component which does exist already', async () => {
let tree = await schematicRunner.runSchematicAsync('component', { name: 'foo', project: 'sandbox' }, appTree).toPromise()

tree = await schematicRunner.runSchematicAsync('component', { name: 'foo', project: 'sandbox' }, appTree).toPromise()

expect(tree.files.filter((f) => f === '/projects/sandbox/src/app/foo/foo.component.ts').length).to.eq(1)
expect(tree.files.filter((f) => f === '/projects/sandbox/src/app/foo/foo.component.html').length).to.eq(1)
expect(tree.files.filter((f) => f === '/projects/sandbox/src/app/foo/foo.component.cy.ts').length).to.eq(1)
expect(tree.files.filter((f) => f === '/projects/sandbox/src/app/foo/foo.component.css').length).to.eq(1)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { chain, externalSchematic, noop, Rule, SchematicContext, Tree } from '@angular-devkit/schematics'
import cypressTest from '../cypress-test'
import path = require('path');

export default function (options: any): Rule {
return (_: Tree, _context: SchematicContext) => {
return chain([
externalSchematic('@schematics/angular', 'component', {
...options,
skipTests: true,
}),
(tree: Tree, _context: SchematicContext) => {
const componentPath = tree.actions.filter((a) => a.path.includes(`${options.name}.component.ts`))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic doesn't work when trying to generate a nested component e.g. ng g c components/hello. The component is generated, but a cypress test is not. This is because

a = 'components/hello/hello.component.ts'
a.path.includes('components/hello.component.ts') === false

Is there a way to get the list of pending changes from the tree? Then we would just have to find a file ending in .component.ts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed up dd2cf7a which fixes ng g c foo/bar example. Take a look and lmk if the change makes sense and then we can get this merged!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this is failing on CI, taking a look...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to generate a cy.ts file? It does not seem to work - tried locally. It does make a spec file, but I don't think that's the goal here, it is?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's passing on Angular-14 but not on Angular-13. I believe it is due to a problem with module resolution, similar to what we've seen with system-tests where it is resolving Angular deps from within the monorepo and not the scaffolded project.

.map((a) => path.dirname(a.path))
.at(0)

return componentPath ? cypressTest({
...options,
component: true,
path: componentPath,
}) : noop()
},
])
}
}
Loading