Is it supported to pass the second argument into the toBe matcher of Jasmine? - jasmine

I found this code snippet from Angular's document, but cannot find this usage from Jasmine's docs. Is this really a supported feature? I just want to make sure that if I use this feature it will not break unexpectedly when upgrading to a newer minor/patch version.
expect(masterService.getValue())
.toBe(stubValue, 'service returned stub value');

The second optional argument of jasmine.Matchers.toBe (named expectationFailOutput) is the message to be displayed when expect fails. Regardless of not appearing in the Jasmine documentation, it is really supported and exists on most methods of the interface jasmine.Matchers.
interface Matchers {
...
toBe(expected: any, expectationFailOutput?: any): boolean;
toEqual(expected: any, expectationFailOutput?: any): boolean;
toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean;
toBeDefined(expectationFailOutput?: any): boolean;
toBeUndefined(expectationFailOutput?: any): boolean;
toBeNull(expectationFailOutput?: any): boolean;
...
toBeTruthy(expectationFailOutput?: any): boolean;
toBeFalsy(expectationFailOutput?: any): boolean;
...
toContain(expected: any, expectationFailOutput?: any): boolean;
toBeLessThan(expected: number, expectationFailOutput?: any): boolean;
toBeLessThanOrEqual(expected: number, expectationFailOutput?: any): boolean;
toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean;
toBeGreaterThanOrEqual(expected: number, expectationFailOutput?: any): boolean;
toBeCloseTo(expected: number, precision?: any, expectationFailOutput?: any): boolean;

The supported method since 3.3 is withContext: https://jasmine.github.io/api/edge/matchers.html#withContext
expect(masterService.getValue()).withContext('service returned stub value')
.toBe(stubValue);

Important Update:
I found passing in the second argument doesn't work for .toEqual() although it works for .toBe(). I'm using jasmine 2.8.16, haven't tried on other versions.
I also found these relevant threads:
https://github.com/jasmine/jasmine/issues/641
https://github.com/adobe/brackets/issues/2752
So now I have changed my mind and would recommend NOT using this feature in your project. If you really want to use it, at least double check to make sure it works with all the needed matchers in your jasmine version.
Original Answer
I found an explanation of this in a different place in Angular's docs, although I still don't see it in Jasmine's docs. With #uminder's response together I feel most likely it's fine to use it. Feel free to give more updates if anyone has anything else to add.
The second parameter to the Jasmine matcher (e.g., 'expected name') is an optional failure label. If the expectation fails, Jasmine appends this label to the expectation failure message. In a spec with multiple expectations, it can help clarify what went wrong and which expectation failed.

Related

Get User Principal Name (UPN) In InnoSetup Installer?

Within the InitializeSetup() function among other actions, when the installer is ran, I would like the installer to retrieve the current UPN. The UserName variable is not sufficient enough. I have also tried methods discussed here utilizing the WTSQuerySessionInformation() function but they don't seem to return what I am looking for. Depending on the organization and setting the UPN should often return some sort of an email address which I am looking for. Can someone shed some light on how to return the full UPN value as a string? Thank you.
EDIT:
I have also tried the GetUserNameExW() function passing in value 8 as an input which refers to UserNamePrincipal, however I am returning an empty value it seems.
function GetUserNameExW(NameFormat: Integer; lpNameBuffer: string; var nSize: DWORD): Boolean;
external 'GetUserNameExW#secur32.dll stdcall';
var
NumChars: DWORD;
OutStr: string;
name: string;
begin
SetLength(OutStr, NumChars);
GetUserNameExW(8, OutStr, NumChars);
name := Copy(OutStr,1,NumChars);
The correct code to call GetUserNameExW to get the current user's userPrincipalName (UPN) attribute would look like this:
function GetUserNameExW(NameFormat: Integer; lpNameBuffer: string; var nSize: DWORD): Boolean;
external 'GetUserNameExW#secur32.dll stdcall';
function GetUserPrincipalName(): string;
var
NumChars: DWORD;
OutStr: string;
begin
result := '';
NumChars := 0;
if (not GetUserNameExW(8, '', NumChars)) and (DLLGetLastError() = 234) then
begin
SetLength(OutStr, NumChars);
if GetUserNameExW(8, OutStr, NumChars) then
result := Copy(OutStr, 1, NumChars);
end;
end;
The value 8 for the NameFormat parameter corresponds to NameUserPrincipal in the EXTENDED_NAME_FORMAT enumeration, and the value 234 is API value ERROR_MORE_DATA.
However--as I pointed out in a comment--if you are looking for an email address, this would not be the code to do that because userPrincipalName (UPN) is a separate user attribute (in fact, in many, if not most organizations, the UPN is different from the user's email address). Also, if you are assuming the UPN to be the same as one of the user's email email addresses, this would also be an incorrect assumption, as the UPN's value is very often not in the list of valid email addresses for a user.
The point is that if you are looking for a reliable way to get a valid email address for a user, the UPN is not going give you one.
I have managed to the solve this issue myself but still not 100% sure on why my previous iteration resulted in odd behavior.
Essentially, I had to add an if check before:
if GetUserNameExW(8, OutStr, NumChars) then

Returning a string from a Function (VAX PASCAL)

This is one for the software archaeologists!
And before you ask why was I even bothering to try to get this to work the reason it is simply because I can - which I think is a perfectly good excuse!
I found that the following code for a procedure compiles using VAX PASCAL (and runs as expected)..
PROCEDURE format(number : INTEGER);
VAR
result : STRING(16);
BEGIN
:
:
writeln(result);
END.
However if turn this into a function and try to return the result as a string it won't compile.
FUNCTION format(number : INTEGER) : STRING(16);
VAR
result : STRING(16);
BEGIN
:
:
format := result;
END.
The error suggests that the error is at type definition for the function.
FUNCTION format(number : INTEGER) : STRING(16);
1
PASCAL-E-TYPCNTDISCR, Type can not be discriminated in this context
I tried using VARYING and ARRAY types instead of STRING but they don't work either. Unfortunately I can't find an example of a function that returns a STRING in SYS$EXAMPLES or in the manuals I found of bitsavers.
Hopefully someone has a better memory than me.
Thanks
"Pascal's type system has been described as "too strong", because the size of an array or string is part of its type, ..." Strong and weak typing
This gives a hint that the String(16) in the function return value is too vague for the compiler.
Fix that by declaring a string type that suits the compiler:
type
String16 = packed array[1..16] of char;
Then you can use that distinct type in the function:
FUNCTION format(number : INTEGER) : String16;
VAR
result : String16;
BEGIN
:
:
format := result;
END.
This is very much what was used in many early implementations of the pascal language (and Turbo Pascal), and is still valid. Modern compilers, like Delphi and FreePascal, has implemented a specialized dynamic array for strings, which covers a more convenient handling of the string type, not depending on declaring a strict size.

Intellisense with Union Types

I find that intellisense is missing when assigning to a var with a type that is a union type. This makes sense - the compiler doesn't know which of the unioned types you are assigning (although at some point it could deduce when it has enough information but it does not do this either...).
Fine - so I can be explicit and cast the assignment to the type I intend, and the intellisense returns. But this leads to a second problem - for some reason it seems that TypeScript will allow the cast of an empty object literal to any interface, but as soon as a single property is added, the object literal must satisfy the entire interface.
If have two direct questions about this behavior, and they are in the comments in the following code example. I realize I could declare the test vars of more specific types - that is not the point of this topic. Thanks for your help.
interface ITestOne {
a: string;
b?: string;
}
interface ITestTwo {
c: string;
}
type EitherType = ITestOne | ITestTwo;
var test1: EitherType = {}; // ERROR, no intellisense to help fill out the required properties in the object literal
var test2: EitherType = {} as ITestOne; // ALLOWED - Why is this allowed?
var test3: EitherType = { b: 'blah' } as ITestOne; // ERROR: property a is missing. Why ISN'T this allowed if the line above is allowed?
UPDATE 2017-0131
Reply From a bug report I opened on the typescript project on this topic:
What type assertion does, it tells the compiler to "shut up" and trust you. The operator behaves both as an upcast and as a downcast operator. The only check is that the one of the types is assignable to the other.
In the example above, for test: {a: string, b?:string} is assignable to {} (which requires no arguments); for test2 {a: string, b?:string} is assignable to {b:string}, since the type of the only required argument in the target b matches. for test3 neither {a: string, b?:string} is assignable to {b:string, x:string} since it is missing x nor {b:string, x:string} to {a: string, b?:string} since it is missing a.
So, when casting, the source or the target are only verified not to be two completely unrelated types (i.e. number and string), but otherwise the assignment is allowed. My test3 case produced the described result in TypeScript 1.7, but it is now allowed in TypeScript 2.1.
My question about how to get meaningful intellisense in this scenario still stands. However, I suspect the answer is that it is simply not supported without the use of a type guard block.

Defining method body inside class declaration?

I'm trying to define class methods all inside of the class declaration in Free Pascal, which I haven't been able to find any examples of online. Currently I have to do it like so:
unit Characters;
{$mode objfpc}{$H+}
// Public
interface
type
TCharacter = class(TOBject)
private
FHealth, FAttack, FDefence: Integer;
procedure SetHealth(newValue: Integer);
public
constructor Create(); virtual;
procedure SayShrek();
function GetHealth(): Integer;
published
property Health: Integer read GetHealth write SetHealth;
end;
// Private
implementation
constructor TCharacter.Create;
begin
WriteLn('Ogres have LAYERS!');
end;
procedure TCharacter.SayShrek;
begin
WriteLn('Shrek!');
end;
procedure TCharacter.SetHealth(newValue: Integer);
begin
FHealth:= FHealth + newValue;
end;
function TCharacter.GetHealth() : Integer;
begin
GetHealth:= FHealth;
end;
end.
Is there any possible way to make this a little cleaner? Defining everything elsewhere looks messy and is unorganized.
EDIT:
To clarify, I'd like to do something along the lines of this:
TMyClass = class(TObject)
public
procedure SayHi();
begin
WriteLn('Hello!');
end;
end;
Instead of having to define it further down. Is that possible?
That is not possible in Pascal. It is just not allowed by its grammar.
It is a fundamental design in Pascal that units are divided in interface (What can be done?) and implementation (How is something done?).
The compiler reads all interface sections before parsing the implementation parts. You might know this from C language. implementation could be described as *.c-files, whereas interface is equivalent to *.h-files in C.
Furthermore such code would heavily decrease readability of interface sections (f.i. class declaratons).
What benefits do you hope to get with that?
No, you can not do this. Pascal has a single-pass compiler from the outset was designed for the single-pass compilation so you can not use something before it will be declared.
As a simple example in pseudocode:
MyClass = class
procedure MethodA;
begin
MethodB; <== At this point the compiler knows nothing about MethodB
end;
procedure MethodB;
begin
end;
end;
It is why each unit have at least two sections: interface (declarations, you can think about it as about C++ header files) and implementation.
However there are some tricks in the language syntax for implementing cyclic declarations where you can use forward declarations.
For the pointers:
PMyRec = ^TMyRec; // Here is TMyRec is not declared yet but compiler can to handle this
TMyRec = record
NextItem: PMyRec;
end;
For the classes:
MyClassA = class; // Forward declaration, class will be fully declared later
MyClassB = class
SomeField: MyClassA;
end;
MyClassA = class
AnotherField: MyClassB;
end;
In the IDE you can use Shift+Ctrl+Up/Down keys to navigate between declaration and implementation of the item.

Typescript rest parameter in the middle of arguments list

I would like to declare a function which last parameter is always a callback. However when i do:
interface Statement extends events.EventEmitter {
bind(...args, callback?:(err?:Error)=>void) : Statement;
}
I get an error
error TS1014: Rest parameter must be last in list
Is it possible in typescript to heve Rest parameter not as a last param in the argument list? Is there any hack that could help me solve this problem?
While a rest parameter needs to be the last one, you can now use variadic tuple types in TS 4.0:
type VarCallback<T extends any[]> = (...args: [...T, (err?: Error) => void]) => void
VarCallback ensures, the last function parameter is a callback type (err?: Error) => void.
For example, declare a function type with the first two parameters string and number:
type MyCallback = VarCallback<[string, number]>
// (a1: string, a2: number, a3: (err?: Error | undefined) => void) => void
const myCb: MyCallback = (s, n, cb) => {/* your implementation */ }
// s,n,cb are strongly typed now
Live code sample
This isn't supported in TypeScript. The best you can do is ...args: any[], or only use libraries with more sensible parameter orderings.
The TypeScript spec for the rest parameter is aligned with ES6's: it is the last arg in the param list. You should change your argument order.
from TypeScript Language Spec (#Parameter List):
A signature’s parameter list consists of zero or more required parameters, followed by zero or more
optional parameters, finally followed by an optional rest parameter.
from ES6: rest parameters - Semantics:
The last parameter in the [[FormalParameters]] List is used for the rest parameter. Of the standard built-in ECMAScript objects, only Function objects implement [[HasRestParameters]].

Resources