Commit 7630206b authored by David Burke's avatar David Burke Committed by Brendan Berkley

Resolve "e2e is broken"

parent aec6db98
...@@ -26,7 +26,6 @@ testem.log ...@@ -26,7 +26,6 @@ testem.log
/typings /typings
# e2e # e2e
/e2e/*.js
/e2e/*.map /e2e/*.map
#System Files #System Files
......
image: trion/ng-cli-karma image: registry.gitlab.com/dasch8/angular-ci:latest
variables: variables:
DOCKER_DRIVER: overlay2 DOCKER_DRIVER: overlay2
...@@ -18,23 +18,7 @@ test: ...@@ -18,23 +18,7 @@ test:
script: script:
- yarn install - yarn install
- yarn run lint - yarn run lint
- yarn run test --progress false --single-run=true --watch=false - yarn run test --progress false --single-run=true --watch=false --browsers=Chromium_CI
e2e-firefox:
stage: test
image: registry.gitlab.com/passit/docker-compose
services:
- docker:dind
script:
- $COMPOSE build web
- $COMPOSE up -d web selenium-firefox
- sleep 15
- $COMPOSE run --no-deps -e CI_JOB_ID=$CI_JOB_ID -e CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME -e CI_COMMIT_SHA=$CI_COMMIT_SHA -e CI_COMMIT_TAG=$CI_COMMIT_TAG -e CI_PROJECT_PATH=$CI_PROJECT_PATH -e FIREFOX=true web e2e:docker
artifacts:
when: on_failure
expire_in: 2 weeks
paths:
- reports/
build-web-assets: build-web-assets:
stage: test stage: test
......
...@@ -168,15 +168,20 @@ ...@@ -168,15 +168,20 @@
} }
}, },
"passit-e2e": { "passit-e2e": {
"root": "", "root": "e2e/",
"sourceRoot": "", "sourceRoot": "",
"projectType": "application", "projectType": "application",
"architect": { "architect": {
"e2e": { "e2e": {
"builder": "@angular-devkit/build-angular:protractor", "builder": "@angular-devkit/build-angular:protractor",
"options": { "options": {
"protractorConfig": "./protractor.conf.js", "protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "passit:serve" "devServerTarget": "passit:serve"
},
"configurations": {
"production": {
"devServerTarget": "passit:serve:production"
}
} }
}, },
"lint": { "lint": {
......
version: '2' version: '2'
services: services:
selenium-chrome: web:
image: selenium/standalone-chrome:3.8 image: registry.gitlab.com/dasch8/angular-ci:latest
volumes:
- /dev/shm:/dev/shm
# so it can load extension
- .:/dist
selenium-firefox:
image: selenium/standalone-firefox:3.8
volumes:
- /dev/shm:/dev/shm
...@@ -19,7 +19,7 @@ services: ...@@ -19,7 +19,7 @@ services:
environment: environment:
DATABASE_URL: postgres://postgres:postgres@db:5432/postgres DATABASE_URL: postgres://postgres:postgres@db:5432/postgres
IS_TEST_MODE: 'True' IS_TEST_MODE: 'True'
IS_PRIVATE_ORG_MODE: "False" IS_PRIVATE_ORG_MODE: "True"
IS_DEBUG: "True" IS_DEBUG: "True"
ports: ports:
- "8000:8000" - "8000:8000"
......
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require("jasmine-spec-reporter");
const { DOCKER, FIREFOX, EXTENSION } = process.env;
exports.config = {
allScriptsTimeout: 21000, // odd number makes it easier to identify
specs: ["./src/**/*.e2e-spec.ts"],
capabilities: FIREFOX
? {
browserName: "firefox"
}
: {
browserName: "chrome"
},
directConnect: true,
framework: "jasmine",
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 41000,
print: function() {}
},
onPrepare() {
require("ts-node").register({
project: require("path").join(__dirname, "./tsconfig.e2e.json")
});
jasmine
.getEnv()
.addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
if (process.env.IS_CI) {
exports.config.capabilities.chromeOptions = {
args: ["no-sandbox", "headless", "disable-gpu"]
};
}
...@@ -48,6 +48,12 @@ describe("Login and Register", () => { ...@@ -48,6 +48,12 @@ describe("Login and Register", () => {
await login(browser, USERNAME, PASSWORD); await login(browser, USERNAME, PASSWORD);
await accountPage.navigateTo(); await accountPage.navigateTo();
await accountPage.resetPasswordButton().click(); await accountPage.resetPasswordButton().click();
const changeBtn = accountPage.changePassBtn();
await EC.browser.wait(
EC.presenceOf(changeBtn),
100,
"Submit button doesn't exist"
);
}); });
it("shows an error if passwords don't match", async () => { it("shows an error if passwords don't match", async () => {
...@@ -89,7 +95,7 @@ describe("Login and Register", () => { ...@@ -89,7 +95,7 @@ describe("Login and Register", () => {
it("logged out and on login page", async () => { it("logged out and on login page", async () => {
const currentUrl = await browser.getCurrentUrl(); const currentUrl = await browser.getCurrentUrl();
expect<any>(currentUrl).toEqual(browser.baseUrl + "login"); expect(currentUrl.endsWith("login")).toBeTruthy();
}); });
it("should login with new password", async () => { it("should login with new password", async () => {
......
...@@ -24,7 +24,7 @@ export class AppPage { ...@@ -24,7 +24,7 @@ export class AppPage {
export class LoginPage { export class LoginPage {
navigateTo = async (testBrowser: ProtractorBrowser) => navigateTo = async (testBrowser: ProtractorBrowser) =>
await testBrowser.get(testBrowser.baseUrl + "login"); await testBrowser.get("/login");
getParagraphText = async (testBrowser: ProtractorBrowser) => getParagraphText = async (testBrowser: ProtractorBrowser) =>
await testBrowser.element(by.className("heading-medium")).getText(); await testBrowser.element(by.className("heading-medium")).getText();
getEmailInput = () => element(by.id("Login Form.email")); getEmailInput = () => element(by.id("Login Form.email"));
...@@ -66,28 +66,28 @@ export class LoginPage { ...@@ -66,28 +66,28 @@ export class LoginPage {
export class RegisterPage { export class RegisterPage {
navigateTo = async () => await browser.get(browser.baseUrl + "/register"); navigateTo = async () => await browser.get(browser.baseUrl + "/register");
clickEmailNextButton = async () => clickEmailNextButton = async (testBrowser: ProtractorBrowser) =>
await element(by.id("email-button")).click(); await testBrowser.element(by.id("email-button")).click();
clickPasswordNextButton = async () => clickPasswordNextButton = async (testBrowser: ProtractorBrowser) =>
await element(by.id("password-button")).click(); await testBrowser.element(by.id("password-button")).click();
clickNewsletterNextButton = async () => clickNewsletterNextButton = async (testBrowser: ProtractorBrowser) =>
await element(by.id("newsletter-button")).click(); await testBrowser.element(by.id("newsletter-button")).click();
getParagraphText = async (testBrowser: ProtractorBrowser) => getParagraphText = async (testBrowser: ProtractorBrowser) =>
await testBrowser.element(by.className("heading-medium")).getText(); await testBrowser.element(by.className("heading-medium")).getText();
getNewsletterText = (testBrowser: ProtractorBrowser) => getNewsletterText = (testBrowser: ProtractorBrowser) =>
testBrowser.element(by.className("register-step__newsletter-input")); testBrowser.element(by.className("register-step__newsletter-input"));
enterEmail = async (testBrowser: ProtractorBrowser, keys: string) => enterEmail = async (testBrowser: ProtractorBrowser, keys: string) =>
await testBrowser.element(by.id("Register Form.email")).sendKeys(keys); await testBrowser.element(by.id("RegisterForm.email")).sendKeys(keys);
enterPassword = async (testBrowser: ProtractorBrowser, keys: string) => enterPassword = async (testBrowser: ProtractorBrowser, keys: string) =>
await testBrowser.element(by.id("Register Form.password")).sendKeys(keys); await testBrowser.element(by.id("RegisterForm.password")).sendKeys(keys);
enterPasswordConfirm = async (testBrowser: ProtractorBrowser, keys: string) => enterPasswordConfirm = async (testBrowser: ProtractorBrowser, keys: string) =>
await testBrowser await testBrowser
.element(by.id("Register Form.passwordConfirm")) .element(by.id("RegisterForm.passwordConfirm"))
.sendKeys(keys); .sendKeys(keys);
enterServerURL = async (testBrowser: ProtractorBrowser, keys: string) => enterServerURL = async (testBrowser: ProtractorBrowser, keys: string) =>
await testBrowser.element(by.id("userUrl")).sendKeys(keys); await testBrowser.element(by.id("userUrl")).sendKeys(keys);
submitByEnter = async (testBrowser: ProtractorBrowser) => { submitByEnter = async (testBrowser: ProtractorBrowser) => {
const passInput = testBrowser.element(by.id("Register Form.password")); const passInput = testBrowser.element(by.id("RegisterForm.password"));
await browser.wait( await browser.wait(
EC.presenceOf(passInput), EC.presenceOf(passInput),
DEFAULT_WAIT, DEFAULT_WAIT,
...@@ -117,11 +117,11 @@ export class ConfirmEmailPage { ...@@ -117,11 +117,11 @@ export class ConfirmEmailPage {
} }
export class AccountPage { export class AccountPage {
navigateTo = async () => await browser.get(browser.baseUrl + "/account"); navigateTo = async () => await browser.get("/account");
navigateToChangePass = async () => navigateToChangePass = async () =>
await browser.get(browser.baseUrl + "/account/change-password"); await browser.get("/account/change-password");
navigateToPassword = async () => navigateToPassword = async () =>
await browser.get(browser.baseUrl + "/account/change-password"); await browser.get("/account/change-password");
resetPasswordButton = () => resetPasswordButton = () =>
element( element(
by.cssContainingText(".account__item-heading", "Change Account Password") by.cssContainingText(".account__item-heading", "Change Account Password")
......
...@@ -55,7 +55,7 @@ describe("List, Add, Edit and Remove Groups", () => { ...@@ -55,7 +55,7 @@ describe("List, Add, Edit and Remove Groups", () => {
it("in groups page and logged in", async () => { it("in groups page and logged in", async () => {
const currentUrl = await browser.getCurrentUrl(); const currentUrl = await browser.getCurrentUrl();
expect(currentUrl).toEqual(browser.baseUrl + "groups"); expect(currentUrl.endsWith("groups")).toBeTruthy();
}); });
it("Add groups", async () => { it("Add groups", async () => {
...@@ -64,7 +64,7 @@ describe("List, Add, Edit and Remove Groups", () => { ...@@ -64,7 +64,7 @@ describe("List, Add, Edit and Remove Groups", () => {
let groupTitleElem: ElementFinder; let groupTitleElem: ElementFinder;
const displayFrom = async () => { const displayFrom = async () => {
await groupsPage.newGroup(); await groupsPage.newGroup(browser);
await browser.wait( await browser.wait(
EC.presenceOf(formEle), EC.presenceOf(formEle),
DEFAULT_WAIT, DEFAULT_WAIT,
......
import { browser, by, element, Key } from "protractor"; import { browser, by, element, Key, ProtractorBrowser } from "protractor";
export class GroupsPage { export class GroupsPage {
navigateTo = async () => await browser.get(browser.baseUrl + "groups"); navigateTo = async () => await browser.get("/groups");
getNewGroupBtnElem = () => element(by.id("showAddGroupform")); getNewGroupBtnElem = () => element(by.id("showAddGroupform"));
// new form // new form
cancelFormByClick = async () => await element(by.className("group-form__cancel-btn")).click(); cancelFormByClick = async () =>
enterGroupName = async (name: string) => await element(by.id("nameInput")).sendKeys(name); await element(by.className("group-form__cancel-btn")).click();
newGroup = async () => await element(by.id("showAddGroupform")).click(); enterGroupName = async (name: string) =>
await element(by.id("nameInput")).sendKeys(name);
newGroup = async (testBrowser: ProtractorBrowser) =>
await testBrowser.element(by.id("showAddGroupform")).click();
// edit form // edit form
deleteGroupByClick = async () => await element(by.className("group-form__delete-btn")).click(); deleteGroupByClick = async () =>
await element(by.className("group-form__delete-btn")).click();
editGroupName = async (name: string) => await this.enterGroupName(name); editGroupName = async (name: string) => await this.enterGroupName(name);
getManageGroupToggleBtnElem = () => element(by.id("manageSecretBtn")); getManageGroupToggleBtnElem = () => element(by.id("manageSecretBtn"));
...@@ -20,18 +24,23 @@ export class GroupsPage { ...@@ -20,18 +24,23 @@ export class GroupsPage {
getFormElem = () => element(by.className("secret__details")); getFormElem = () => element(by.className("secret__details"));
getGroupTitleElem = () => element(by.css(".secret__heading .secret__title")); getGroupTitleElem = () => element(by.css(".secret__heading .secret__title"));
getNameFormInputElem = () => element(by.id("nameInput")); getNameFormInputElem = () => element(by.id("nameInput"));
getNewlyCreatedGroupElem = () => element.all(by.css(".secret-list-item")).last(); getNewlyCreatedGroupElem = () =>
element.all(by.css(".secret-list-item")).last();
saveButton = () => element(by.className("group-form__save-btn")); saveButton = () => element(by.className("group-form__save-btn"));
saveGroupByClick = async () => await element(by.className("group-form__save-btn")).click(); saveGroupByClick = async () =>
submitGroupByEnter = async () => await element(by.id("nameInput")).sendKeys(Key.ENTER); await element(by.className("group-form__save-btn")).click();
submitGroupByEnter = async () =>
await element(by.id("nameInput")).sendKeys(Key.ENTER);
membersInput = () => element(by.id("membersInput")); membersInput = () => element(by.id("membersInput"));
// specific member // specific member
groupMember = (name: string) => element(by.cssContainingText(".option", `${name}`)); groupMember = (name: string) =>
element(by.cssContainingText(".option", `${name}`));
getMembersInput = () => element(by.css(".multiple input")); getMembersInput = () => element(by.css(".multiple input"));
membersList = () => element(by.tagName("select-dropdown")); membersList = () => element(by.tagName("select-dropdown"));
getDropDownItem = (name: string) => element(by.xpath(`//span[contains(string(), "${name}")]`)); getDropDownItem = (name: string) =>
element(by.xpath(`//span[contains(string(), "${name}")]`));
} }
...@@ -24,9 +24,8 @@ import { DEFAULT_WAIT, login, register } from "./shared"; ...@@ -24,9 +24,8 @@ import { DEFAULT_WAIT, login, register } from "./shared";
.manage() .manage()
.timeouts() .timeouts()
.setScriptTimeout(30 * 1000); .setScriptTimeout(30 * 1000);
(global as any).screenshotBrowsers["browser2"] = browser2;
// (global as any).screenshotBrowsers["browser1"] = browser;
secretsPage = new SecretsPage(); secretsPage = new SecretsPage();
groupsPage = new GroupsPage();
browser.sleep(50); browser.sleep(50);
...@@ -50,24 +49,25 @@ import { DEFAULT_WAIT, login, register } from "./shared"; ...@@ -50,24 +49,25 @@ import { DEFAULT_WAIT, login, register } from "./shared";
afterAll(async () => { afterAll(async () => {
browser2.close(); browser2.close();
delete (global as any).screenshotBrowsers.browser2;
browser.executeScript("window.localStorage.clear();"); browser.executeScript("window.localStorage.clear();");
browser.executeScript("window.sessionStorage.clear();"); browser.executeScript("window.sessionStorage.clear();");
}); });
it("in groups page and logged in", async () => { it("in groups page and logged in", async () => {
groupsPage = new GroupsPage();
await groupsPage.navigateTo(); await groupsPage.navigateTo();
const currentUrl = await browser.getCurrentUrl(); const currentUrl = await browser.getCurrentUrl();
expect<any>(currentUrl).toEqual(browser.baseUrl + "groups"); expect(currentUrl.endsWith("groups")).toBeTruthy();
}); });
it("It creates a group and adds second user to group", async () => { it("It creates a group and adds second user to group", async () => {
// Create second user
await register(browser2, USERNAME2, PASSWORD2, PASSWORD2); await register(browser2, USERNAME2, PASSWORD2, PASSWORD2);
await browser2.refresh(); await browser2.refresh();
await login(browser2, USERNAME2, PASSWORD2); await login(browser2, USERNAME2, PASSWORD2);
await browser.refresh();
await groupsPage.newGroup(); // First user creates group
browser.refresh(); // Cheap way to refresh contacts data
await groupsPage.newGroup(browser);
await groupsPage.enterGroupName(groupName); await groupsPage.enterGroupName(groupName);
const elem = groupsPage.getMembersInput(); const elem = groupsPage.getMembersInput();
...@@ -75,6 +75,7 @@ import { DEFAULT_WAIT, login, register } from "./shared"; ...@@ -75,6 +75,7 @@ import { DEFAULT_WAIT, login, register } from "./shared";
.actions() .actions()
.mouseMove(elem) .mouseMove(elem)
.click(); .click();
// First user adds second user to group
await groupsPage.getMembersInput().sendKeys(USERNAME2); await groupsPage.getMembersInput().sendKeys(USERNAME2);
const groupClick = groupsPage.getDropDownItem(USERNAME2); const groupClick = groupsPage.getDropDownItem(USERNAME2);
await groupClick.click(); await groupClick.click();
...@@ -101,7 +102,6 @@ import { DEFAULT_WAIT, login, register } from "./shared"; ...@@ -101,7 +102,6 @@ import { DEFAULT_WAIT, login, register } from "./shared";
"Can see list" "Can see list"
); );
await searchElem.isDisplayed(); await searchElem.isDisplayed();
// const formElement = secretsPage.getFormElem(browser);
await secretsPage.selectAddNewPassword(); await secretsPage.selectAddNewPassword();
await secretsPage.enterName(secretName); await secretsPage.enterName(secretName);
...@@ -113,86 +113,39 @@ import { DEFAULT_WAIT, login, register } from "./shared"; ...@@ -113,86 +113,39 @@ import { DEFAULT_WAIT, login, register } from "./shared";
await group.click(); await group.click();
await secretsPage.submitByEnter(); await secretsPage.submitByEnter();
// await browser.wait(
// EC.stalenessOf(formElement),
// DEFAULT_WAIT,
// "secret not saved and form is still open"
// );
// const secret = await secretsPage.getSecretText(secretName);
// expect<any>(secret).toBe(secretName);
}); });
it("Decrypts the password", async () => { it("Decrypts the shared password from a group", async () => {
browser2.refresh();
const currentSecretToggleBtnElem = secretsPage.getToggleButton( const currentSecretToggleBtnElem = secretsPage.getToggleButton(
browser2, browser2,
secretName secretName
); );
const button = currentSecretToggleBtnElem const button = currentSecretToggleBtnElem
.element(secretsPage.getManageSecretToggleBtnElem()) .element(secretsPage.getManageSecretToggleBtnElem(browser2))
.locator(); .locator();
button.click(); button.click();
const formElement = secretsPage.getFormElem(browser); const formElement = secretsPage.getFormElem(browser2);
await EC.browser.wait( await browser.wait(
EC.presenceOf(formElement), EC.presenceOf(formElement),
DEFAULT_WAIT, DEFAULT_WAIT,
"Secret Form not present" "Secret Form not present"
); );
const currentPasswordToggleBtnElem = browser.element( const currentPasswordToggleBtnElem = browser2.element(
by.className("t-password-viewer__actions") by.className("t-password-viewer__actions")
); );
currentPasswordToggleBtnElem.click(); currentPasswordToggleBtnElem.click();
const passwordNameText = async () => {
const passwordNameElem = await secretsPage.getPasswordNameElem(browser);
return passwordNameElem;
};
expect<any>(await passwordNameText()).toBe("hunter2");
const closeButton = secretsPage.getManageSecretToggleBtnElem();
await closeButton.click();
});
it("It decrypts shared group password", async () => {
await browser2.sleep(50);
await secretsPage.navigateTo(browser2);
const E = browser2.ExpectedConditions;
const div = secretsPage.getToggleButton(browser2, secretName);
const button = div.element(by.id("manageSecretBtn"));
button.click();
const formElement = secretsPage.getFormElem(browser2);
await E.browser.wait(
E.presenceOf(formElement),
DEFAULT_WAIT,
"Secret Form not displayed"
);
await browser2.sleep(50);
const currentPasswordToggleBtnElem = secretsPage.getShowPasswordToggleBtnElem(
browser2
);
await E.browser.wait(
E.presenceOf(currentPasswordToggleBtnElem),
DEFAULT_WAIT,
"Secret Form not displayed"
);
await currentPasswordToggleBtnElem.click();
await browser2.sleep(50);
const passwordNameText = async () => { const passwordNameText = async () => {
const passwordNameElem = await secretsPage.getPasswordNameElem(browser2); const passwordNameElem = await secretsPage.getPasswordNameElem(browser2);
return passwordNameElem; return passwordNameElem;
}; };
expect<any>(await passwordNameText()).toBe("hunter2"); expect(await passwordNameText()).toBe("hunter2");
const closeButton = secretsPage.getManageSecretToggleBtnElem(); const closeButton = secretsPage.getManageSecretToggleBtnElem(browser2);
await closeButton.click(); await closeButton.click();
}); });
}); });
...@@ -7,7 +7,7 @@ export class SecretsPage { ...@@ -7,7 +7,7 @@ export class SecretsPage {
getSearchElem = () => element(by.id("search")); getSearchElem = () => element(by.id("search"));
navigateTo = async (testBrowser: ProtractorBrowser) => navigateTo = async (testBrowser: ProtractorBrowser) =>
await testBrowser.get(testBrowser.baseUrl + "/list"); await testBrowser.get("/list");
selectAddNewPassword = async () => selectAddNewPassword = async () =>
await element(by.id("add-new-password-button")).click(); await element(by.id("add-new-password-button")).click();
enterName = async (keys: string) => enterName = async (keys: string) =>
...@@ -35,7 +35,8 @@ export class SecretsPage { ...@@ -35,7 +35,8 @@ export class SecretsPage {
getAllSecretsElem = () => element.all(by.css(".secret-list-item")); getAllSecretsElem = () => element.all(by.css(".secret-list-item"));
getManageSecretToggleBtnElem = () => element(by.id("manageSecretBtn")); getManageSecretToggleBtnElem = (testBrowser: ProtractorBrowser) =>
testBrowser.element(by.id("manageSecretBtn"));
getPasswordNameElem = async (testBrowser: ProtractorBrowser) => getPasswordNameElem = async (testBrowser: ProtractorBrowser) =>
await testBrowser await testBrowser
......
...@@ -28,10 +28,10 @@ export async function register( ...@@ -28,10 +28,10 @@ export async function register(
const registerPage = new RegisterPage(); const registerPage = new RegisterPage();
expect(await registerPage.getParagraphText(testBrowser)).toEqual("Sign Up"); expect(await registerPage.getParagraphText(testBrowser)).toEqual("Sign Up");
await registerPage.enterEmail(testBrowser, username); await registerPage.enterEmail(testBrowser, username);
await registerPage.clickEmailNextButton(); await registerPage.clickEmailNextButton(testBrowser);
await registerPage.enterPassword(testBrowser, password); await registerPage.enterPassword(testBrowser, password);
await registerPage.enterPasswordConfirm(testBrowser, passwordConfirm); await registerPage.enterPasswordConfirm(testBrowser, passwordConfirm);
await registerPage.clickPasswordNextButton(); await registerPage.clickPasswordNextButton(testBrowser);
if (isExtension) { if (isExtension) {
await registerPage.enterServerURL(testBrowser, SERVER_URL); await registerPage.enterServerURL(testBrowser, SERVER_URL);
} }
...@@ -41,7 +41,7 @@ export async function register( ...@@ -41,7 +41,7 @@ export async function register(
DEFAULT_WAIT, DEFAULT_WAIT,
"Newsletter text should be shown" "Newsletter text should be shown"
); );
await registerPage.clickNewsletterNextButton(); await registerPage.clickNewsletterNextButton(testBrowser);
const confirmEmailPage = new ConfirmEmailPage(); const confirmEmailPage = new ConfirmEmailPage();
const codeElem = confirmEmailPage.getCodeElem(testBrowser); const codeElem = confirmEmailPage.getCodeElem(testBrowser);
await EC.browser.wait( await EC.browser.wait(
......
{
"compilerOptions": {
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es2016"
],
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types":[
"jasmine",
"node"
]
}
}
{ {
"extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"sourceMap": true, "outDir": "../out-tsc/app",
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es2016"
],
"outDir": "../out-tsc/e2e",
"module": "commonjs", "module": "commonjs",
"target": "es5", "target": "es5",
"types":[ "types": [
"jasmine", "jasmine",
"jasminewd2",
"node" "node"
] ]
} }
} }
\ No newline at end of file
// Karma configuration file, see link for more information // Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html // https://karma-runner.github.io/0.13/config/configuration-file.html
module.exports = function (config) { module.exports = function(config) {
config.set({ config.set({
basePath: '', basePath: "",
frameworks: ['jasmine', '@angular-devkit/build-angular'], frameworks: ["jasmine", "@angular-devkit/build-angular"],
plugins: [ plugins: [
require('karma-jasmine'), require("karma-jasmine"),
require('karma-chrome-launcher'), require("karma-chrome-launcher"),
require('karma-jasmine-html-reporter'), require("karma-jasmine-html-reporter"),
require('