Skip to content

Commit

Permalink
feat: rewrite of ngx-sub-form without inheritance
Browse files Browse the repository at this point in the history
This is a major architecture change which is brought without any breaking change 😄!

We've split up the code base in 2: Old one and new one.
The old one hasn't moved at all but is now deprecated (not removed yet!).
You can keep using the old one for a bit and have a smooth/incremental update to use the new API.

Few changes that you have to note with the new API:
- Only works with Angular 9 or more
- The app needs to have Ivy activated (this is because we use `ɵmarkDirty` internally. If it ever gets removed we'll probably have to ask to provide the `ChangeDetectorRef` but we were able to around this for now!)
- We got rid of inheritance 🙌
- Form errors on a FormArray are now an object instead of an array. Previously the array contained null values on all the fields without any error. It's now an object containing only the ones with errors and you can access them using the index

Please start upgrading to the new API as soon as possible as we stop supporting the old API as of today and will remove it in a near release.

This closes #171 for the major architectural changes and also the following issues as a result:
- closes #82
- closes #86
- closes #93
- closes #133
- closes #143
- closes #144
- closes #149
- closes #160
- closes #168
  • Loading branch information
maxime1992 committed Nov 21, 2021
1 parent 75e2d60 commit fef8cce
Show file tree
Hide file tree
Showing 67 changed files with 2,555 additions and 525 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*.launch
.settings/
*.sublime-workspace
.history

# IDE - VSCode
.vscode/*
Expand Down
10 changes: 6 additions & 4 deletions cypress/helpers/data.helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { OneListing, ListingType } from '../../src/app/interfaces/listing.interface';
import { UnreachableCase } from '../../src/app/shared/utils';
import { CrewMember } from '../../src/app/interfaces/crew-member.interface';
import { DroidType } from '../../src/app/interfaces/droid.interface';
import { ListingType, OneListing } from '../../src/app/interfaces/listing.interface';
import { VehicleType } from '../../src/app/interfaces/vehicle.interface';
import { CrewMember } from '../../src/app/interfaces/crew-member.interface';
import { UnreachableCase } from '../../src/app/shared/utils';

export interface ListElement {
readonly title: string;
Expand Down Expand Up @@ -140,4 +140,6 @@ export const hardcodedElementToTestElement = (item: OneListing): ListElement =>
export const hardcodedElementsToTestList = (items: OneListing[]): ListElement[] =>
items.map(item => hardcodedElementToTestElement(item));

export const extractErrors = (errors: JQuery<HTMLElement>) => cy.wrap(JSON.parse(errors.text().trim()));
export const extractErrors = (errors: JQuery<HTMLElement>) => {
return JSON.parse(errors.text().trim());
};
122 changes: 52 additions & 70 deletions cypress/helpers/dom.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { DroidType } from '../../src/app/interfaces/droid.interface';
import { ListingType } from '../../src/app/interfaces/listing.interface';
import { VehicleType } from '../../src/app/interfaces/vehicle.interface';
import { extractErrors, FormElement, ListElement } from './data.helper';

const getTextFromTag = (element: HTMLElement, tag: string): string =>
Cypress.$(element)
Expand Down Expand Up @@ -36,13 +35,6 @@ const getCrewMembers = (element: HTMLElement): { firstName: string; lastName: st
}))
.get();

export const expectAll = (selector: string, cb: (el: Cypress.Chainable) => void) =>
cy.get(selector).then($elements => {
$elements.each((_, $element) => {
cb(cy.wrap($element));
});
});

export const DOM = {
get createNewButton() {
return cy.get('*[data-create-new]');
Expand All @@ -61,19 +53,6 @@ export const DOM = {
},
};
},
get objList(): Cypress.Chainable<ListElement[]> {
return DOM.list.elements.cy.then($elements => {
return $elements
.map((_, element) => ({
title: getTextFromTag(element, 'title'),
type: getTextFromTag(element, 'type'),
price: getTextFromTag(element, 'price'),
subType: getTextFromTag(element, 'sub-type'),
details: getTextFromTag(element, 'details'),
}))
.get();
});
},
};
},
get readonlyToggle() {
Expand All @@ -85,59 +64,11 @@ export const DOM = {
return cy.get('app-listing');
},
get errors() {
return {
get cy() {
return cy.get(`*[data-errors]`);
},
get obj() {
return DOM.form.errors.cy.then(extractErrors);
},
};
return cy.get(`*[data-errors]`);
},
get noErrors() {
return cy.get(`*[data-no-error]`);
},
getObj(type: VehicleType): Cypress.Chainable<FormElement> {
const getVehicleObj = (element: HTMLElement, vehicleType: VehicleType) =>
({
Spaceship: {
spaceshipForm: {
color: getTextFromInput(element, 'input-color'),
canFire: getToggleValue(element, 'input-can-fire'),
crewMembers: getCrewMembers(element),
wingCount: +getTextFromInput(element, 'input-number-of-wings'),
},
},
Speeder: {
speederForm: {
color: getTextFromInput(element, 'input-color'),
canFire: getToggleValue(element, 'input-can-fire'),
crewMembers: getCrewMembers(element),
maximumSpeed: +getTextFromInput(element, 'input-maximum-speed'),
},
},
}[vehicleType]);

return DOM.form.cy.then($element => {
return $element
.map((_, element) => ({
title: getTextFromTag(element, 'title'),
price: getTextFromTag(element, 'price'),
inputs: {
id: getTextFromInput(element, 'input-id'),
title: getTextFromInput(element, 'input-title'),
imageUrl: getTextFromInput(element, 'input-image-url'),
price: getTextFromInput(element, 'input-price'),
listingType: getSelectedOptionFromSelect(element, 'select-listing-type'),
vehicleForm: {
vehicleType: getSelectedOptionFromSelect(element, 'select-vehicle-type'),
...getVehicleObj(element, type),
},
},
}))
.get()[0];
});
},
get elements() {
return {
get title() {
Expand Down Expand Up @@ -195,3 +126,54 @@ export const DOM = {
};
},
};

const getVehicleObj = (element: HTMLElement, vehicleType: VehicleType) =>
({
Spaceship: {
spaceshipForm: {
color: getTextFromInput(element, 'input-color'),
canFire: getToggleValue(element, 'input-can-fire'),
crewMembers: getCrewMembers(element),
wingCount: +getTextFromInput(element, 'input-number-of-wings'),
},
},
Speeder: {
speederForm: {
color: getTextFromInput(element, 'input-color'),
canFire: getToggleValue(element, 'input-can-fire'),
crewMembers: getCrewMembers(element),
maximumSpeed: +getTextFromInput(element, 'input-maximum-speed'),
},
},
}[vehicleType]);

export const getFormValue = (form: JQuery<HTMLElement>, type: VehicleType) =>
form
.map((_, element) => ({
title: getTextFromTag(element, 'title'),
price: getTextFromTag(element, 'price'),
inputs: {
id: getTextFromInput(element, 'input-id'),
title: getTextFromInput(element, 'input-title'),
imageUrl: getTextFromInput(element, 'input-image-url'),
price: getTextFromInput(element, 'input-price'),
listingType: getSelectedOptionFromSelect(element, 'select-listing-type'),
vehicleForm: {
vehicleType: getSelectedOptionFromSelect(element, 'select-vehicle-type'),
...getVehicleObj(element, type),
},
},
}))
.get()[0];

export const getFormList = ($elements: JQuery<HTMLElement>) => {
return $elements
.map((_, element) => ({
title: getTextFromTag(element, 'title'),
type: getTextFromTag(element, 'type'),
price: getTextFromTag(element, 'price'),
subType: getTextFromTag(element, 'sub-type'),
details: getTextFromTag(element, 'details'),
}))
.get();
};
11 changes: 11 additions & 0 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,14 @@ import './commands';

// Alternatively you can use CommonJS syntax:
// require('./commands')

Cypress.on('window:before:load', win => {
cy.stub(win.console, 'error', msg => {
cy.now('task', 'error', msg);
throw new Error(msg); // all we needed to add!
});

cy.stub(win.console, 'warn', msg => {
cy.now('task', 'warn', msg);
});
});
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"test": "yarn lib:test:watch",
"commit": "git add . && git-cz",
"readme:build": "embedme README.md && yarn run prettier README.md --write",
"readme:check": "yarn readme:build && ! git status | grep README.md || (echo 'You must commit build and commit changes to README.md!' && exit 1)"
"readme:check": "yarn readme:build && ! git status | grep README.md || (echo 'You must commit build and commit changes to README.md!' && exit 1)",
"ngcc": "[ ! -f ./node_modules/.bin/ngcc ] || node --max_old_space_size=8000 ./node_modules/.bin/ngcc",
"postinstall":"yarn run ngcc"
},
"private": true,
"dependencies": {
Expand All @@ -50,6 +52,7 @@
"commitizen": "4.0.3",
"core-js": "3.6.4",
"fast-deep-equal": "3.1.1",
"ngx-observable-lifecycle": "1.0.1",
"rxjs": "6.5.4",
"tslib": "1.10.0",
"uuid": "3.4.0",
Expand All @@ -66,7 +69,7 @@
"@types/jasminewd2": "2.0.8",
"@types/node": "13.7.2",
"codelyzer": "5.2.1",
"cypress": "4.0.2",
"cypress": "4.5.0",
"cz-conventional-changelog": "3.1.0",
"embedme": "1.20.0",
"http-server-spa": "1.3.0",
Expand All @@ -82,6 +85,7 @@
"semantic-release": "17.0.4",
"ts-node": "8.6.2",
"tsconfig-paths-webpack-plugin": "3.2.0",
"tsdef": "0.0.13",
"tslint": "6.0.0",
"typescript": "3.7.5"
},
Expand Down
Loading

0 comments on commit fef8cce

Please sign in to comment.