Je suis en train de migrer une application Angular de la v6 vers la v7. Tout va bien sauf tout test qui compare les énumérations. Lorsque j'exécute mes tests, j'obtiens de nombreuses erreurs concernant mes énumérations comme suit
{ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/spec", "module": "commonjs", "target": "es5", "baseUrl": "", "types": [ "jasmine", "node" ] }, "files": [ "test.ts", "polyfills.ts" ], "include": [ "**/*.spec.ts", "**/*.d.ts" ] }
Voici un exemple de test en cours d'exécution:
{ "compileOnSave": false, "compilerOptions": { "importHelpers": true, "preserveConstEnums": true, "outDir": "./dist/out-tsc", "baseUrl": "src", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "noUnusedLocals": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2016", "dom" ] } }
Cependant, si je transforme mon énumération en nombre, mes tests fonctionnent parfaitement! Ce serait loin d'être idéal pour mettre à jour mes spécifications partout comme ceci:
"dependencies": { "@angular/animations": "~7.2.0", "@angular/common": "~7.2.0", "@angular/compiler": "~7.2.0", "@angular/core": "~7.2.0", "@angular/forms": "~7.2.0", "@angular/http": "~7.2.0", "@angular/platform-browser": "~7.2.0", "@angular/platform-browser-dynamic": "~7.2.0", "@angular/router": "~7.2.0", "core-js": "^2.5.4", "rxjs": "~6.4.0", "tslib": "^1.9.0", "zone.js": "~0.8.26", "@angular/cdk": "^7.0.3", "@angular/flex-layout": "7.0.0-beta.24", "@angular/material": "7.3.6", "hammerjs": "2.0.8", "intl": "1.2.5", "jshashes": "1.0.7", "lodash-es": "4.17.11", "request-promise-native": "1.0.5", "stream": "0.0.2", "timers": "0.1.1", "url-search-params-polyfill": "5.0.0", "xml2js": "0.4.19" }, "devDependencies": { "@angular-devkit/build-angular": "~0.13.0", "@angular/cli": "~7.3.7", "@angular/compiler-cli": "~7.2.0", "@angular/language-service": "~7.2.0", "@types/node": "~8.9.4", "@types/jasmine": "~2.8.8", "@types/jasminewd2": "~2.0.3", "codelyzer": "~4.5.0", "jasmine-core": "~2.99.1", "jasmine-spec-reporter": "~4.2.1", "karma": "~4.0.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "~2.0.1", "karma-jasmine": "~1.1.2", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.4.0", "ts-node": "~7.0.0", "tslint": "~5.11.0", "typescript": "~3.2.2", "@types/lodash-es": "4.17.1", "gulp": "3.9.1", "gulp-stylelint": "7.0.0", "jasmine-data-provider": "2.2.0", "karma-cli": "1.0.1", "karma-junit-reporter": "1.2.0", "karma-parallel": "0.3.0", "karma-spec-reporter": "0.0.32", "lodash": "4.17.11", "moment": "2.22.2", "npm": "6.0.0", "protractor-beautiful-reporter": "1.2.5", "protractor-jasmine2-screenshot-reporter": "0.5.0", "stylelint": "9.6.0", "stylelint-order": "1.0.0", "tslint-jasmine-noSkipOrFocus": "1.0.9" }
Je ne sais pas si j'ai manqué quelque chose dans mon package.json
. J'ai comparé un nouveau projet angular 7 à mes propres projets et les versions de angular core, dactylographié, jasmin et karma entre eux sont les mêmes.
Comment puis-je obtenir mes tests pour comparer correctement les énumérations? Voici mon package.json
expect(component.selectedPlanDuration).toBe(<number> PlanDuration.SixMonths);
tsconfig.json:
export enum PlanDuration { SixMonths, TwelveMonths } ... it('should toggle plan duration to six months if the event source id is the toggle duration and the event is not checked', () => { component.selectedPlanDuration = PlanDuration.TwelveMonths; component.handleToggle(event); expect(component.selectedPlanDuration).toBe(PlanDuration.SixMonths); // Tests cannot run because of errors here });
tsconfig.spec .json
ERROR in src/.../some-thing.component.spec.ts: error TS2345: Argument of type 'PlanDuration.SixMonths' is not assignable to parameter of type 'Expected<PlanDuration.TwelveMonths>'.
3 Réponses :
J'ai rencontré des problèmes il y a quelque temps où Angular me disait qu'il ne pouvait pas accéder à MyEnumValue of undefined
. Après quelques manipulations, j'ai trouvé que l'exportation de toutes les énumérations en tant que const
et l'ajout de "preserveConstEnums": true
à mon tsconfig.json le permettaient très bien.
Mais les énumérations sont toujours des nombres, sauf indication contraire, et heureusement n'ont pas besoin de cast, mais la compilation d'énumérations de Typescript peut parfois être funky de la même manière que les interfaces le sont.
Edit:
In votre composant, assurez-vous que:
// If you give this a default value, TypeScript will assume // that the only "valid" type is PlanDuration.TwelveMonths // Type evaluates to: PlanDuration | number between 0 and 1; selectedPlanDuration: PlanDuration = PlanDuration.TwelveMonths; // Type evaluates to: PlanDuration.TwelveMonths | 1; selectedPlanDuration = PlanDuration.TwelveMonths
J'ai essayé votre suggestion, ainsi que la correspondance d'un tsconfig entre une application vanilla ng7 et notre application de production, et je n'ai pas pu faire fonctionner cela. Je pense cependant que c'est un problème avec TS et je continuerai d'enquêter.
essayez expect (component.selectedPlanDuration.valueOf ())
Hé en fait, quel type d'annotation avez-vous donné au composant? J'ai l'impression que vous l'avez défini comme quelque chose de funky, et que le type attribué à selectedPlanDuration
est littéralement PlanDuration.TwelveMonths
. Typescript vous permet d'affecter un «type» à une variable sous la forme d'une valeur unique d'un seul type. soit q: 3 = 4; // erreur
J'ai mis à jour ma réponse pour couvrir quelque chose qui pourrait être le problème, mais qui n'a pas été fourni dans votre question. C'est probablement le problème
Mon composant a ce membre: public selectedPlanDuration: PlanDuration = PlanDuration.SixMonths;
. La suggestion de valueOf
fonctionne bien, cependant, pas idéale pour corriger de nombreuses spécifications pour contenir cette méthode.
Pouvez-vous publier votre fichier tsconfig complet?
@JonathanScmold, j'ai posté mon tsconfig dans ma question maintenant
continuons cette discussion en chat .
TL;DR Solution rapide: accédez à Voilà :) Pour plus de détails, lisez la suite: Je crois que c'est un bug dans la définition des types de jasmine. J'ai mis en place un nouvel espace de travail ng7 et j'essaye de reproduire votre problème. Voici ma conclusion: Il y a deux fichiers Je suis Je ne sais pas à 100% comment ces deux éléments fonctionnent ensemble, mais ils déclarent des types conflictuels pour les mêmes utils jasmine. Par exemple: Le problème est maintenant dans Cette ligne Le moyen le plus simple de le corriger est de le corriger manuellement. La solution est déjà donnée au début. Bravo. node_modules/@types/jasmine/index.d.ts
, recherchez type Expected code>
// jasmine/index.d.ts
declare namespace jasmine {
interface Matchers<T> {
toBe(expected: Expected<T>, expectationFailOutput?: any): boolean;
.d.ts
liés au jasmin dans l'espace de travail: // jasminewd2/index.d.ts
declare namespace jasmine {
interface Matchers<T> {
toBe(expected: any, expectationFailOutput?: any): Promise<void>;
...
// package.json
...
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
// Change this line:
// type Expected<T> = T | ObjectContaining<T> | Any | Spy;
// to:
type Expected<T> = any;
jasmine / index.d.ts
. toBe (attendu: attendu
est tout simplement FAUX. Ceci est un cas de test, vous êtes certainement autorisé à tester par rapport à n'importe quelle
valeur. Pourtant, Expected
est déclaré comme un type complexe sans point.
Une note latérale. Personnellement, je pense que ts-check un fichier source de cas de test au moment de la compilation est une exagération et devrait être désactivé pour de bon. Le contrôle Ts à l'heure de départ est bien cependant.
Cette solution rapide a du sens, mais comment cela fonctionnerait-il dans une configuration de serveur de production? Peut-être qu'une meilleure option (autre que la soumission d'un PR) est de remplacer cette définition de type et de l'utiliser dans les tests. Bien que cela nécessiterait toujours un changement dans chaque fichier qui compare les énumérations et que l'OP ne veut pas faire cela.
@Nanotron La fusion de déclarations devrait aider. Je n'ai pas d'ordinateur autour de moi, je ne peux donc pas le tester, mais je suppose que cela devrait fonctionner: ajoutez un patchJasmine.d.ts
quelque part qui est inclus dans tsconfig.json
, puis dans le fichier vous ajoutez ceci: declare namespace jasmine {type Attendu
.
J'ai rencontré le même problème lors de l'implémentation de nouveaux tests dans un projet Angular 7 (sans migration de 6 à 7). Si vous préférez une solution de contournement plutôt qu'une modification susceptible d'affecter les futures mises à jour de Karma / Jasmine, vous pouvez permuter les comparaisons afin que l'énumération soit la première:
expect(PlanDuration.SixMonths).toBe(component.selectedPlanDuration);
Je ne sais pas pourquoi cela a été voté, mais je suis arrivé ici en cherchant pourquoi les Enums de mes tests où des erreurs et cette méthode étaient les plus plausibles pour moi (et j'imagine que la plupart des gens qui rencontrent ce message) mettre en place.
Essayez plutôt "export const enum ...", et dans votre TSConfig, essayez de définir
preserveConstEnums: true
. Les énumérations sont en fait des nombres sauf indication contraire, et n'ont pas besoin de transtypage, mais Typescript compile funky avec les énumérations que j'ai trouvées@JonathanSchmold, pouvez-vous poster ceci comme réponse? Je peux essayer votre suggestion lundi matin et si cela fonctionne, je vous décernerai volontiers cette prime.
Je peux certainement :)
Je suppose que cela pourrait être un problème avec Karma et Jasmine. J'en ai vu et j'ai dû passer de la 4e version à la 3.99
C'est un bug dans la définition de type de jasmin. Vérifiez ma réponse pour plus de détails et comment y remédier.