Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two StateHandler types defined #1057

Closed
2 of 5 tasks
paul-kuihi opened this issue Feb 7, 2023 · 4 comments · Fixed by #1062
Closed
2 of 5 tasks

Two StateHandler types defined #1057

paul-kuihi opened this issue Feb 7, 2023 · 4 comments · Fixed by #1062
Labels
bug Indicates an unexpected problem or unintended behavior

Comments

@paul-kuihi
Copy link

paul-kuihi commented Feb 7, 2023

Software versions

  • OS: Mac OSX 13.1
  • Consumer Pact library: Pact JS v10.4.1
  • Provider Pact library: Pact JS v10.4.1
  • Node Version: 18.12.1

Issue Checklist

Please confirm the following:

  • I have upgraded to the latest
  • I have the read the FAQs in the Readme
  • I have triple checked, that there are no unhandled promises in my code and have read the section on intermittent test failures
  • I have set my log level to debug and attached a log file showing the complete request/response cycle
  • For bonus points and virtual high fives, I have created a reproduceable git repository (see below) to illustrate the problem

I raised this in the pact-js slack channel and was asked to raise this issue.

Expected behaviour

Creating StateHandlers as per the documentation results in no Typing errors from TS.

Actual behaviour

When attempting to use the setup/teardown properties on the provider state handlers Typescript complains that it doesn't match the type it's expecting. TS is finding two types with the same name and merging them (StateHandlers I believe). It gives the error:

(property) 'my state': {
    setup: () => Promise<void>;
    teardown: () => Promise<void>;
}
Type '{ setup: () => Promise<void>; teardown: () => Promise<void>; }' is not assignable to type 'StateHandler & ((state: string, params?: { [name: string]: string; } | undefined) => Promise<unknown>)'.
  Type '{ setup: () => Promise<void>; teardown: () => Promise<void>; }' is not assignable to type 'StateFuncWithSetup & ((state: string, params?: { [name: string]: string; } | undefined) => Promise<unknown>)'.
    Type '{ setup: () => Promise<void>; teardown: () => Promise<void>; }' is not assignable to type '(state: string, params?: { [name: string]: string; } | undefined) => Promise<unknown>'.
      Type '{ setup: () => Promise<void>; teardown: () => Promise<void>; }' provides no match for the signature '(state: string, params?: { [name: string]: string; } | undefined): Promise<unknown>'.ts(2322)

Steps to reproduce

Create a state handler definition such as:

'Whatever your state name is': {
    setup: (parameters) => {
      // do your setup here
      // return a promise if you need to
    },
    teardown: (parameters) => {
      // do your teardown here
      // return a promise if you need to
    },
  },

TS will complain as above.

As a workaround, we've created a shim type. An alternative as mentioned by @TimothyJones in the slack thread is to define your own StateHandler type until this is fixed up.

Relevant log files

N/A

@paul-kuihi paul-kuihi added the bug Indicates an unexpected problem or unintended behavior label Feb 7, 2023
TimothyJones added a commit to TimothyJones/pact-js that referenced this issue Feb 16, 2023
…lers` from `StateHandlers` avoiding the conflicting type problem introduced in pact-foundation#882. Fixes pact-foundation#1057
@TimothyJones
Copy link
Contributor

I raised a PR that fixes this.

@iamchughmayank
Copy link

Hi there 👋

I was facing the same problem and stumbled upon this issue. I followed the slack thread linked in the issue and tried to workaround this but I still faced some issues.

While the PR is under review, I was hoping to get some help with the suggested workaround:

type ShimmedVerifierOptions = Omit<VerifierOptions, 'stateHandlers'> & {
	stateHandlers: StateHandlers;
  };

let baseOptions: ShimmedVerifierOptions;

		baseOptions = {
...
			stateHandlers: {
				'my consumer state': {
					setup: async () => {
						console.log('setup');
					}
				}
			}
		};

Error:

Type '{ setup: () => Promise<void>; }' is not assignable to type '(state: string, params?: { [name: string]: string; }) => Promise<unknown>'.
  Object literal may only specify known properties, and 'setup' does not exist in type '(state: string, params?: { [name: string]: string; }) => Promise<unknown>'.ts(2322)

TIA 💙

@TimothyJones
Copy link
Contributor

I don't think that workaround would work unless you defined your own StateHandler type and didn't import Pact's one (which is what I think the OP did).

The workaround I suggested was in the thread was:

Define your state handlers explicitly as one of the types it accepts (so typescript doesn’t try to figure it out)

const myConsumerState: StateFuncWithSetup = {
  setup: async (params) => {
    console.log(params);
  },
};

const baseOptions: ShimmedVerifierOptions = {
...
			stateHandlers: {
				'my consumer state': myConsumerState,
			},
		};

PS: The PR is #1062. Sorry I forgot to link it before.

@iamchughmayank
Copy link

Thanks, @TimothyJones :) I am quite new to TypeScript and I think I will take some time to learn a lot of concepts here (probably the PR will merge in before that 😓 )

If I understand correctly, OP did not use
import { StateHandlers } from '@pact-foundation/pact';

However, while checking out the StatefuncWithSetup, I also saw that StateHandlers are exposed from the same place. And, I tried doing:

import { StateHandlers } from '@pact-foundation/pact/src/dsl/verifier/proxy/types';

Then, I "shimmy-ed" the VerifierOptions like so:

import { Verifier, LogLevel, VerifierOptions } from '@pact-foundation/pact';
import { StateHandlers } from '@pact-foundation/pact/src/dsl/verifier/proxy/types';

type ShimmedVerifierOptions = Omit<VerifierOptions, 'stateHandlers'> & {
	stateHandlers: StateHandlers;
  };

Once, I did that, the type compatibility issues did not occur:

cones baseOptions: ShimmedVerifierOptions = {
			stateHandlers: {
				'fetch all blogs for site': {
					setup: async () => {
						const siteId = await funcToGetSiteId();
						return Promise.resolve({site: siteId});
					}
				  }
			}
}

However, with this implementation, I am getting a 500 error in pact setup:


INFO (30342): pact@10.4.1: Verifying provider
INFO (30342): pact@10.4.1: debug request/response logging enabled
INFO (30342): pact-core@13.13.4: Verifying Pacts.
INFO (30342): pact-core@13.13.4: Verifying Pact Files
DEBUG (30342): pact-core@13.13.4: Initalising native core at log level 'debug'
2023-02-28T13:25:51.035753Z DEBUG ThreadId(02) verify_interaction{interaction="a request to get blog by siteId"}: hyper::client::pool: pooling idle connection for ("http", 127.0.0.1:57203)
DEBUG (30342): pact@10.4.1: incoming request: {"body":{"action":"setup","params":{},"state":"fetch all blogs for site"},"headers":{"content-type":"application/json","accept":"*/*","accept-encoding":"gzip, deflate","host":"127.0.0.1:57203","content-length":"65"},"method":"POST","path":"/_pactSetup"}
DEBUG (30342): pact@10.4.1: setting up state '{"action":"setup","params":{},"state":"fetch all blogs for site"}'
DEBUG (30342): pact@10.4.1: setting up state 'fetch all blogs for site'
DEBUG (30342): pact@10.4.1: outgoing response: {"body":"{}","headers":{"x-powered-by":"Express","content-type":"application/json; charset=utf-8","content-length":"2","etag":"W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\""},"status":500}
DEBUG (30342): pact@10.4.1: incoming request: {"body":{"action":"setup","params":{},"state":"fetch all blogs for site"},"headers":{"content-type":"application/json","accept":"*/*","accept-encoding":"gzip, deflate","host":"127.0.0.1:57203","content-length":"65"},"method":"POST","path":"/_pactSetup"}
DEBUG (30342): pact@10.4.1: setting up state '{"action":"setup","params":{},"state":"fetch all blogs for site"}'
DEBUG (30342): pact@10.4.1: setting up state 'fetch all blogs for site'
DEBUG (30342): pact@10.4.1: outgoing response: {"body":"{}","headers":{"x-powered-by":"Express","content-type":"application/json; charset=utf-8","content-length":"2","etag":"W/\"2
 RUNS  test/contract/my-spec.ts
DEBUG ThreadId(02) verify_interaction{interaction="a request to get blog by siteId"}: hyper::client::pool: reuse idle connection for ("http", 127.0.0.1:57203)
DEBUG tokio-runtime-worker hyper::proto::h1::io: flushed 214 bytes
DEBUG tokio-runtime-worker hyper::proto::h1::io: parsed 7 headers
DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body is content-length (2 bytes)
DEBUG tokio-runtime-worker hyper::proto::h1::conn: incoming body completed
DEBUG ThreadId(02) verify_interaction{interaction="a request to get blog by siteId"}: hyper::client::pool: pooling idle connection for ("http", 127.0.0.1:57203)
DEBUG ThreadId(02) verify_interaction{interaction="a request to get blog by siteId"}: pact_verifier::provider_client: State change request: Response { url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(57203), path: "/_pactSetup", query: None, fragment: None }, status: 500, headers: {"x-powered-by": "Express", "content-type": "application/json; charset=utf-8", "content-length": "2", "etag": "W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"", "date": "Tue, 28 Feb 2023 13:25:52 GMT", "connection": "keep-alive", "keep-alive": "timeout=5"} }
DEBUG ThreadId(02) verify_interaction{interaction="a request to get blog by siteId"}: pact_verifier: State Change: "ProviderState { name: "fetch all blogs for site", params: {} }" -> Err(Provider state failed: Invalid status code: 500)
ERROR ThreadId(02) verify_interaction{interaction="a request to get blog by siteId"}: pact_verifier: Provider setup state change for 'fetch all blogs for site' has failed - MismatchResult::Error("Invalid status code: 500", None)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants