{"id":18764475,"url":"https://github.com/theintern/intern-angular","last_synced_at":"2025-12-07T07:30:20.294Z","repository":{"id":25021646,"uuid":"96942587","full_name":"theintern/intern-angular","owner":"theintern","description":"Intern helper library for Angular 2+","archived":false,"fork":false,"pushed_at":"2017-09-10T02:47:28.000Z","size":229,"stargazers_count":0,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-29T05:42:12.007Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theintern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-11T22:31:11.000Z","updated_at":"2017-09-10T02:48:00.000Z","dependencies_parsed_at":"2022-08-07T11:15:13.046Z","dependency_job_id":null,"html_url":"https://github.com/theintern/intern-angular","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-angular","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-angular/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-angular/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theintern%2Fintern-angular/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theintern","download_url":"https://codeload.github.com/theintern/intern-angular/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239662746,"owners_count":19676435,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T18:29:58.737Z","updated_at":"2025-12-07T07:30:20.235Z","avatar_url":"https://github.com/theintern.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intern + Angular\n\nThis is a test project to demonstrate using Intern with Angular 4+. It contains [all of the specs](https://angular.io/generated/live-examples/testing/app-specs.eplnkr.html) from Angular's test guide as well as [some extras](https://angular.io/generated/live-examples/testing/bag-specs.eplnkr.html). Specs have been reformatted and converted to using Intern best practices as outlined below.\n\n## Get started\n\n### Clone the repo\n\n```shell\ngit clone https://github.com/bryanforbes/intern-angular\ncd intern-angular\n```\n\n### Install npm packages\n\nInstall the `npm` packages described in the `package.json` and verify that it works:\n\n```shell\nnpm install\nnpm start\n```\n\nThe `npm start` command builds (compiles TypeScript and copies assets) the application into `dist/`, watches for changes to the source files, and runs `lite-server` on port `3000`.\n\nShut it down manually with `Ctrl-C`.\n\n#### npm scripts\n\nThese are the most useful commands defined in `package.json`:\n\n* `npm start` - runs the TypeScript compiler, asset copier, and a server at the same time, all three in \"watch mode\".\n* `npm run build` - runs the TypeScript compiler and asset copier once.\n* `npm run build:watch` - runs the TypeScript compiler and asset copier in \"watch mode\"; when changes occur to source files, they will be recompiled or copied into `dist/`.\n* `npm run lint` - runs `tslint` on the project files.\n* `npm run serve` - runs `lite-server`.\n\nThese are the test-related scripts:\n\n* `npm test` - builds the application and runs Intern tests (both unit and functional) one time.\n* `npm run ci` - cleans, lints, and builds the application and runs Intern tests (both unit and functional) one time.\n\n\n## Techniques\n\nBecause Intern seamlessly handles asynchronous testing, there is no reason to use `async`, `fakeAsync`, or `tick` from `@angular/core/testing`. Furthermore, because TypeScript introduced downlevel asynchronous function support in version 2.1, the use of `async` and `await` has been leveraged to write these tests.\n\n### Intern `bdd` interfaces\n\nThe first change made to all spec files was to assign the `describe`, `it`, `beforeEach`, and `expect` functions from the Intern plugins:\n\n```ts\nconst { describe, it, beforeEach } = intern.getPlugin('interface.bdd');\nconst { expect } = intern.getPlugin('chai');\n```\n\nMost of these interfaces behave similarly to jasmine or mocha with a couple of exceptions. First, `before`, `after`, `beforeEach`, `afterEach`, and `it` can all take a function that returns a promise or is defined with `async` and Intern will wait until that promise has resolved before proceeding to the next test/lifecycle function.\n\n**It should be noted** that Intern currently (alpha.9) does not wait for a promise to resolve if there are multiple of the same lifecycle functions in one `describe` block. For instance, this is quite common to see in Angular tests:\n\n```ts\nbeforeEach(async(() =\u003e {\n\tTestBed.configureTestingModule({\n\t\tdeclarations: [ DashboardHeroComponent ],\n\t})\n\t.compileComponents();\n}));\n\nbeforeEach(() =\u003e {\n\tfixture = TestBed.createComponent(DashboardHeroComponent);\n\tcomp    = fixture.componentInstance;\n\theroEl  = fixture.debugElement.query(By.css('.hero'));\n});\n```\n\nUsing `async` and `await`, this can be easily rewritten into a single function with Intern:\n\n```ts\nbeforeEach(async () =\u003e {\n\tawait TestBed.configureTestingModule({\n\t\tdeclarations: [ DashboardHeroComponent ],\n\t})\n\t.compileComponents();\n\n\tfixture = TestBed.createComponent(DashboardHeroComponent);\n\tcomp    = fixture.componentInstance;\n\theroEl  = fixture.debugElement.query(By.css('.hero'));\n});\n```\n\nSince Intern comes with Chai bundled, many of the expectations had to be rewritten. Most of these were simply changing `.toBe()` to `.to.equal()` or `toMatch()` to `to.match()`.\n\nAnother change was from using jasmine's `spyOn()` to Sinon.JS's `spy()` and `stub()` as well as `sinon-chai` to add expectations for stubs and spies to `expect()`.\n\n### Asynchronous functions\n\nSimilar to the lifecycle functions, any invocation of `it` that used Angular's `async()` or `fakeAsync()` was rewritten to use an asynchronous function. For instance:\n\n```ts\nit('should show quote after getQuote promise (async)', async(() =\u003e {\n\tfixture.detectChanges();\n\n\tfixture.whenStable().then(() =\u003e { // wait for async getQuote\n\t\tfixture.detectChanges();        // update view with quote\n\t\texpect(el.textContent).toBe(testQuote);\n\t});\n}));\n\nit('should select hero on click', fakeAsync(() =\u003e {\n\tconst expectedHero = HEROES[1];\n\tconst li = page.heroRows[1];\n\tli.dispatchEvent(newEvent('click'));\n\ttick();\n\t// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService\n\texpect(comp.selectedHero).toEqual(expectedHero);\n}));\n```\n\nThese can be easily rewritten to the following:\n\n```ts\nit('should show quote after getQuote promise', async () =\u003e {\n\tfixture.detectChanges();\n\n\tawait fixture.whenStable(); // wait for async getQuote\n\tfixture.detectChanges();    // update view with quote\n\texpect(el.textContent).to.equal(testQuote);\n});\n\nit('should select hero on click', async () =\u003e {\n\tconst expectedHero = HEROES[1];\n\tconst li = page.heroRows[1];\n\tli.dispatchEvent(newEvent('click'));\n\tawait comp.heroes; // the promise returned from the service\n\texpect(comp.selectedHero).to.deep.equal(expectedHero);\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheintern%2Fintern-angular","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheintern%2Fintern-angular","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheintern%2Fintern-angular/lists"}