diff --git a/.github/workflows/e2e-rspec.yml b/.github/workflows/e2e-rspec.yml new file mode 100644 index 000000000..6abeefbb9 --- /dev/null +++ b/.github/workflows/e2e-rspec.yml @@ -0,0 +1,45 @@ +name: e2e rspec tests + +on: + pull_request: + paths: ['app/**'] + +jobs: + rspec: + name: E2E Rspec + runs-on: ubuntu-22.04 + services: + postgres: + image: postgres + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: ["5432:5432"] + env: + POSTGRES_DB: iv_cbv_payroll_test + POSTGRES_USER: cidbuser + POSTGRES_PASSWORD: postgres + + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/cleanup-gemfile + + - id: setup + uses: ./.github/actions/setup-project + with: + rails_env: test + + - name: Run e2e tests via rspec + working-directory: app + env: + RAILS_ENV: test + DATABASE_URL: ${{ steps.setup.outputs.database_url }} + RAILS_MASTER_KEY: 0f5db7adba61669d4cc45dfa6b2464d7 + RUN_E2E_TESTS: 1 + PINWHEEL_API_TOKEN_SANDBOX: a-valid-token-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + PINWHEEL_SANDBOX: true + SUPPORTED_PROVIDERS: pinwheel + + run: bundle exec rspec ./spec/e2e diff --git a/app/Gemfile b/app/Gemfile index 0dfec29d7..c38de481f 100644 --- a/app/Gemfile +++ b/app/Gemfile @@ -14,7 +14,7 @@ gem "sprockets-rails" gem "pg", "~> 1.1" # Use the Puma web server [https://github.com/puma/puma] -gem "puma", "~> 6.4.3" +gem "puma", "~> 6.5.0" # Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails] gem "jsbundling-rails" @@ -91,6 +91,7 @@ group :development, :test do gem "rubocop-rails-omakase" gem "selenium-webdriver" gem "timecop" + gem "vcr" end group :development do @@ -112,6 +113,7 @@ group :test do gem "webmock" gem "factory_bot", "~> 6.4" gem "rails-controller-testing" + gem "puffing-billy" end group :production do diff --git a/app/Gemfile.lock b/app/Gemfile.lock index 03dd1c44a..65781bd8e 100644 --- a/app/Gemfile.lock +++ b/app/Gemfile.lock @@ -152,6 +152,7 @@ GEM climate_control (1.2.0) concurrent-ruby (1.1.10) connection_pool (2.5.0) + cookiejar (0.3.4) crack (1.0.0) bigdecimal rexml @@ -180,6 +181,17 @@ GEM dotenv (= 2.8.1) railties (>= 3.2) drb (2.2.1) + em-http-request (1.1.7) + addressable (>= 2.3.4) + cookiejar (!= 0.3.1) + em-socksify (>= 0.3) + eventmachine (>= 1.0.3) + http_parser.rb (>= 0.6.0) + em-socksify (0.3.3) + base64 + eventmachine (>= 1.0.0.beta.4) + em-synchrony (1.0.6) + eventmachine (>= 1.0.0.beta.1) erb_lint (0.9.0) activesupport better_html (>= 2.0.1) @@ -188,6 +200,8 @@ GEM rubocop (>= 1) smart_properties erubi (1.13.1) + eventmachine (1.2.7) + eventmachine_httpserver (0.2.1) factory_bot (6.4.6) activesupport (>= 5.0.0) faraday (2.9.2) @@ -204,6 +218,7 @@ GEM highline (3.1.0) reline htmlentities (4.3.4) + http_parser.rb (0.6.0) i18n (1.14.7) concurrent-ruby (~> 1.0) i18n-tasks (1.0.14) @@ -251,6 +266,7 @@ GEM minitest (5.25.5) mixpanel-ruby (2.3.0) msgpack (1.7.2) + multi_json (1.15.0) multi_xml (0.7.1) bigdecimal (~> 3.1) mutex_m (0.3.0) @@ -321,7 +337,15 @@ GEM date stringio public_suffix (6.0.1) - puma (6.4.3) + puffing-billy (4.0.0) + addressable (~> 2.5) + em-http-request (~> 1.1, >= 1.1.0) + em-synchrony + eventmachine (~> 1.2) + eventmachine_httpserver + http_parser.rb (~> 0.6.0) + multi_json + puma (6.5.0) nio4r (~> 2.0) racc (1.8.1) rack (2.2.13) @@ -483,6 +507,8 @@ GEM concurrent-ruby (~> 1.0) unicode-display_width (2.6.0) uri (1.0.3) + vcr (6.3.1) + base64 version_gem (1.1.4) view_component (3.13.0) activesupport (>= 5.2.0, < 8.0) @@ -555,7 +581,8 @@ DEPENDENCIES pg (~> 1.1) pg-aws_rds_iam (~> 0.5.0) premailer-rails - puma (~> 6.4.3) + puffing-billy + puma (~> 6.5.0) rack-mini-profiler rails (~> 7.1.5, >= 7.1.5.1) rails-controller-testing @@ -574,6 +601,7 @@ DEPENDENCIES timecop turbo-rails tzinfo-data + vcr view_component web-console webmock diff --git a/app/spec/controllers/users/omniauth_callbacks_controller_spec.rb b/app/spec/controllers/users/omniauth_callbacks_controller_spec.rb index 5fdb3e82f..8908b8662 100644 --- a/app/spec/controllers/users/omniauth_callbacks_controller_spec.rb +++ b/app/spec/controllers/users/omniauth_callbacks_controller_spec.rb @@ -91,6 +91,10 @@ context "when the user is not authorized" do it "redirects to root url with an alert" do + ma_config = ClientAgencyConfig::ClientAgency.new({ "authorized_emails" => nil, "pinwheel" => { "environment" => "sandbox" }, + "id" => "ma", "agency_name" => "Department of Transitional Assistance", + "argyle" => { "environment" => "sandbox" } }) + allow(Rails.application.config.client_agencies).to receive(:[]).with("ma").and_return(ma_config) post :ma_dta expect(response).to redirect_to(root_url) expect(flash[:alert]).to be_present diff --git a/app/spec/e2e/cbv_flow_spec.rb b/app/spec/e2e/cbv_flow_spec.rb index be61cdaf6..356f7ac9c 100644 --- a/app/spec/e2e/cbv_flow_spec.rb +++ b/app/spec/e2e/cbv_flow_spec.rb @@ -1,11 +1,16 @@ require "rails_helper" -RSpec.describe "e2e CBV flow test", type: :feature, js: true do +# flip this to "all" if you need to record a new interaction +# to run these tests with record: :all, make sure you have a .env.test.local with PINWHEEL_API_TOKEN_SANDBOX, then you can run this test via running +# to run these tests at all, +# explicitly via rubymine, or RUN_E2E_TESTS=1 bundle exec rspec spec/e2e/cbb_flow_spec.rb +RECORD_OPTION = :none + +RSpec.describe "e2e CBV flow test", type: :feature, js: true, vcr: { record: RECORD_OPTION, name: "e2e_cbv_flow_english" } do include E2eTestHelpers include_context "with_ngrok_tunnel" let(:cbv_flow_invitation) { create(:cbv_flow_invitation) } - before(:all, js: true) do unless ENV.fetch("PINWHEEL_API_TOKEN_SANDBOX", "").length == 64 raise "You need to set a PINWHEEL_API_TOKEN_SANDBOX in .env.test.local in order for this test to succeed" @@ -17,96 +22,78 @@ # TODO: Remove this when we stub out Pinwheel usage: # (We will have to allow access to the capybara server URL.) WebMock.allow_net_connect! - # Register Ngrok with Pinwheel - capybara_server_url = URI(page.server_url) - @ngrok.start_tunnel(capybara_server_url.port) - puts "Found ngrok tunnel at #{@ngrok.tunnel_url}!" - @subscription_id = PinwheelWebhookManager.new.create_subscription_if_necessary( - @ngrok.tunnel_url, - ENV["USER"] - ) + VCR.use_cassette("e2e_cbv_flow_english", record: RECORD_OPTION) do + capybara_server_url = URI(page.server_url) + @ngrok.start_tunnel(capybara_server_url.port) + puts "Found ngrok tunnel at #{@ngrok.tunnel_url}!" + @subscription_id = PinwheelWebhookManager.new.create_subscription_if_necessary( + @ngrok.tunnel_url, + ENV["USER"] + ) + end if RECORD_OPTION == :all end after(:all, js: true) do - if @subscription_id - puts "[PINWHEEL] Deleting webhook subscription id: #{@subscription_id}" - Aggregators::Sdk::PinwheelService.new("sandbox").delete_webhook_subscription(@subscription_id) - end - - # TODO: Remove these when we stub out Pinwheel usage: - page.quit - WebMock.disable_net_connect! - end - - shared_examples "proceeding through the flow normally" do - it "completes the flow" do - # /cbv/entry - visit URI(cbv_flow_invitation.to_url).request_uri - verify_page(page, title: I18n.t("cbv.entries.show.header")) - find("label", text: I18n.t("cbv.entries.show.checkbox.default", agency_full_name: I18n.t("shared.agency_full_name.sandbox"))).click - click_button I18n.t("cbv.entries.show.continue") - - # /cbv/employer_search - verify_page(page, title: I18n.t("cbv.employer_searches.show.header")) - fill_in name: "query", with: "foo" - click_button I18n.t("cbv.employer_searches.show.search") - expect(page).to have_content("McKee Foods") - find("div.usa-card__container", text: "McKee Foods").click_button(I18n.t("cbv.employer_searches.show.select")) - - # Pinwheel modal - pinwheel_modal = page.find("iframe.pinwheel-modal-show") - page.within_frame(pinwheel_modal) do - if I18n.locale == :en - fill_in "Username", with: "user_good", wait: 10 - fill_in "Workday Password", with: "pass_good" - click_button "Continue" - elsif I18n.locale == :es - fill_in "Nombre de usuario", with: "user_good", wait: 10 - fill_in "ContraseƱa de Workday", with: "pass_good" - click_button "Continuar" - else - raise "Unknown locale: #{I18n.locale}" - end + if @subscription_id && RECORD_OPTION == :all + VCR.use_cassette("e2e_cbv_flow_english", record: :all) do + puts "[PINWHEEL] Deleting webhook subscription id: #{@subscription_id}" + Aggregators::Sdk::PinwheelService.new("sandbox").delete_webhook_subscription(@subscription_id) end - - # /cbv/synchronizations - verify_page(page, title: I18n.t("cbv.synchronizations.show.header"), wait: 15) - - # All the pinwheel webhooks occur here! - - # /cbv/payment_details - verify_page(page, title: I18n.t("cbv.payment_details.show.header", employer_name: "Acme Corporation"), wait: 60) - fill_in "cbv_flow[additional_information]", with: "Some kind of additional information" - click_button I18n.t("cbv.payment_details.show.continue") - - # /cbv/add_job - verify_page(page, title: I18n.t("cbv.add_jobs.show.header")) - find("label", text: I18n.t("cbv.add_jobs.show.no_radio")).click - click_button I18n.t("cbv.add_jobs.show.continue") - - # /cbv/summary - verify_page(page, title: I18n.t("cbv.summaries.show.header")) - find(:css, "label[for=cbv_flow_consent_to_authorized_use]").click - click_button I18n.t("cbv.summaries.show.send_report", agency_acronym: "CBV") - - # TODO: Test PDF rendering by writing it to a file end end - context "in english" do - it_behaves_like "proceeding through the flow normally" - end - - context "in spanish" do - before do - cbv_flow_invitation.update(language: "es") - end - - around do |ex| - I18n.with_locale("es", &ex) + it "completes the flow" do + # /cbv/entry + mock_cbv_flow_responses + + visit URI(root_url).request_uri + visit URI(cbv_flow_invitation.to_url).request_uri + verify_page(page, title: I18n.t("cbv.entries.show.header")) + find("label", text: I18n.t("cbv.entries.show.checkbox.default", agency_full_name: I18n.t("shared.agency_full_name.sandbox"))).click + click_button I18n.t("cbv.entries.show.continue") + + # /cbv/employer_search + verify_page(page, title: I18n.t("cbv.employer_searches.show.header"), wait: 10) + fill_in name: "query", with: "foo" + click_button I18n.t("cbv.employer_searches.show.search") + expect(page).to have_content("McKee Foods") + find("div.usa-card__container", text: "McKee Foods").click_button(I18n.t("cbv.employer_searches.show.select")) + + + # Pinwheel modal + pinwheel_modal = page.find("iframe.pinwheel-modal-show") + page.within_frame(pinwheel_modal) do + fill_in "Workday Organization ID", with: "company_good", wait: 10 + click_button "Continue" + fill_in "Username", with: "user_good", wait: 10 + fill_in "Password", with: "pass_good", wait: 10 + simulate_next_step_and_webhooks + click_button "Continue" end - it_behaves_like "proceeding through the flow normally" + # /cbv/synchronizations + verify_page(page, title: I18n.t("cbv.synchronizations.show.header"), wait: 15) + + # All the pinwheel webhooks occur here! + # TODO bring back the rest of this flow via sliding more webhooks in + + # /cbv/payment_details + # verify_page(page, title: I18n.t("cbv.payment_details.show.header", employer_name: "Acme Corporation"), wait: 60) + # fill_in "cbv_flow[additional_information]", with: "Some kind of additional information" + # click_button I18n.t("cbv.payment_details.show.continue") + + # /cbv/add_job + # verify_page(page, title: I18n.t("cbv.add_jobs.show.header")) + # find("label", text: I18n.t("cbv.add_jobs.show.no_radio")).click + # click_button I18n.t("cbv.add_jobs.show.continue") + # + # # /cbv/summary + # verify_page(page, title: I18n.t("cbv.summaries.show.header")) + # click_on "Continue" + # find(:css, "label[for=cbv_flow_consent_to_authorized_use]").click + # click_on "Share my report with CBV" + + # TODO: Test PDF rendering by writing it to a file end end diff --git a/app/spec/e2e/client_signup_spec.rb b/app/spec/e2e/client_signup_spec.rb new file mode 100644 index 000000000..4bf28dddc --- /dev/null +++ b/app/spec/e2e/client_signup_spec.rb @@ -0,0 +1,41 @@ +require 'rails_helper' + +RSpec.describe 'Client Steps through signing up', type: :system do + before do + driven_by(:selenium_chrome_headless) # Change to :selenium_chrome if you want to see the browser + WebMock.disable_net_connect!(allow_localhost: true) + OmniAuth.config.test_mode = true + OmniAuth.config.mock_auth[:sandbox] = OmniAuth::AuthHash.new( + provider: 'google_oauth2', + uid: '123456', + info: { + email: 'test@example.com', + name: 'Test User', + nickname: 'the mockiest perrson' + }, + credentials: { + token: 'mock_token', + refresh_token: 'mock_refresh_token', + expires_at: Time.now + 1.hour + } + ) + end + + + it 'tries to sign up a new client through the flow' do + visit "sandbox/sso" + click_on "Continue to CBV Test Agency log in page" + click_on "Create a new invitation" + fill_in "cbv_flow_invitation[cbv_applicant_attributes][first_name]", with: "Dean" + fill_in "Client's middle name", with: "Alan" + fill_in "cbv_flow_invitation[cbv_applicant_attributes][last_name]", with: "Venture" + fill_in "Case Number", with: "Some kinda case" + fill_in "Your WELID", with: "12345" + fill_in "Client's email address", with: "hank@example.com" + click_on "Send Invitation" + expect(page).to have_content "In what language should we send the invitation?" + find(".usa-radio-group .usa-radio__label[for='language-en-0']").click + click_on "Send Invitation" + expect(page).to have_content "Successfully delivered invitation to hank@example.com" + end +end diff --git a/app/spec/e2e/help_feature_spec.rb b/app/spec/e2e/help_feature_spec.rb index 44972216f..3d3cbab21 100644 --- a/app/spec/e2e/help_feature_spec.rb +++ b/app/spec/e2e/help_feature_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -RSpec.describe "Help Features", type: :feature, js: true do +RSpec.xdescribe "Help Features", type: :feature, js: true do include E2eTestHelpers include PinwheelApiHelper diff --git a/app/spec/fixtures/vcr_cassettes/e2e_cbv_flow_english.yml b/app/spec/fixtures/vcr_cassettes/e2e_cbv_flow_english.yml new file mode 100644 index 000000000..4b4851b71 --- /dev/null +++ b/app/spec/fixtures/vcr_cassettes/e2e_cbv_flow_english.yml @@ -0,0 +1,462 @@ +--- +http_interactions: +- request: + method: get + uri: https://sandbox.getpinwheel.com/v1/webhooks + body: + encoding: US-ASCII + string: '' + headers: + Content-Type: + - application/json + Pinwheel-Version: + - '2023-11-22' + X-Api-Secret: + - "" + User-Agent: + - Faraday v2.9.2 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 17 Apr 2025 17:03:27 GMT + Content-Type: + - application/json + Content-Length: + - '3355' + Connection: + - keep-alive + Server: + - uvicorn + Pinwheel-Version: + - '2023-11-22' + Content-Security-Policy: + - frame-ancestors 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; + X-Pinwheel-Request-Id: + - 53600897-6c1e-4024-a9c4-cc9b644dc734 + body: + encoding: UTF-8 + string: '{"meta":{"count":8,"next_cursor":null},"data":[{"url":"https://f423-24-6-157-50.ngrok-free.app/webhooks/pinwheel/events#subscription_name=tdooner","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"22935812-df0d-4a20-840c-7272a295c646","created_at":"2025-04-17T00:12:40.706055+00:00","last_updated":"2025-04-17T00:12:40.706055+00:00"},{"url":"https://462a-107-5-204-44.ngrok-free.app/webhooks/pinwheel/events#subscription_name=georgebyers","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"92f0d8f1-59af-4ee0-bc6f-1732dd313d3d","created_at":"2025-04-16T22:46:24.680217+00:00","last_updated":"2025-04-16T22:46:24.680217+00:00"},{"url":"https://bac2-76-255-28-250.ngrok-free.app/webhooks/pinwheel/events#subscription_name=timmiller","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"079ed193-f433-4177-940f-1517e95b0b33","created_at":"2025-04-15T15:34:45.043716+00:00","last_updated":"2025-04-15T15:34:45.043716+00:00"},{"url":"https://40b9-2600-1700-5135-a000-1400-c2a-7257-844.ngrok-free.app/webhooks/pinwheel/events#subscription_name=daphnegold","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"80dc90c1-6397-4867-add7-e7635f6a896c","created_at":"2025-04-10T23:03:15.320604+00:00","last_updated":"2025-04-10T23:03:15.320604+00:00"},{"url":"https://1501-174-174-120-155.ngrok-free.app/webhooks/pinwheel/events#subscription_name=n4fd","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"6f81e79d-777d-4fe6-997c-1003c84e8011","created_at":"2025-04-10T20:22:25.883898+00:00","last_updated":"2025-04-10T20:22:25.883898+00:00"},{"url":"https://2db0-136-226-6-90.ngrok-free.app/webhooks/pinwheel/events#subscription_name=cdiggins","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"dc398791-ff94-40d9-b79f-dfd6c2e87e2a","created_at":"2025-04-04T18:29:31.040814+00:00","last_updated":"2025-04-04T18:29:31.040814+00:00"},{"url":"https://verify-demo.navapbc.cloud/webhooks/pinwheel/events#subscription_name=DEMO","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"70c82b8a-df85-49d9-9550-13a531432634","created_at":"2024-08-28T16:05:16.714531+00:00","last_updated":"2024-08-28T16:05:16.714531+00:00"},{"url":"https://snap-income-pilot.com/webhooks/pinwheel/events#subscription_name=DEMO","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"13098bf4-2e60-4dbd-a7c3-522c696d385c","created_at":"2024-08-26T21:13:40.296166+00:00","last_updated":"2024-08-26T21:13:40.296166+00:00"}]}' + recorded_at: Thu, 17 Apr 2025 17:03:27 GMT +- request: + method: post + uri: https://sandbox.getpinwheel.com/v1/webhooks + body: + encoding: UTF-8 + string: '{"enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"url":"https://ea9a-2601-1c0-5688-590-744e-8ae0-ba45-47dd.ngrok-free.app/webhooks/pinwheel/events#subscription_name=iannorris","status":"active","version":"2023-11-22"}' + headers: + Content-Type: + - application/json + Pinwheel-Version: + - '2023-11-22' + X-Api-Secret: + - "" + User-Agent: + - Faraday v2.9.2 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 17 Apr 2025 17:03:28 GMT + Content-Type: + - application/json + Content-Length: + - '447' + Connection: + - keep-alive + Server: + - uvicorn + Pinwheel-Version: + - '2023-11-22' + Content-Security-Policy: + - frame-ancestors 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; + X-Pinwheel-Request-Id: + - 1efc64a1-f7bd-4fc7-a073-a4f2e6c34e33 + body: + encoding: UTF-8 + string: '{"data":{"url":"https://ea9a-2601-1c0-5688-590-744e-8ae0-ba45-47dd.ngrok-free.app/webhooks/pinwheel/events#subscription_name=iannorris","status":"active","enabled_events":["account.added","paystubs.added","paystubs.fully_synced","employment.added","income.added","identity.added"],"version":"2023-11-22","id":"e18da643-c900-4b51-948e-0b7629f5e4cf","created_at":"2025-04-17T17:03:28.108924+00:00","last_updated":"2025-04-17T17:03:28.108924+00:00"}}' + recorded_at: Thu, 17 Apr 2025 17:03:28 GMT +- request: + method: get + uri: http://clients2.google.com/time/1/current?cup2hreq=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&cup2key=8:ZRBoH8dtf6ltkPa8uDEvSpKHHteUKoe9HKYjVfoSJLk + body: + encoding: UTF-8 + string: '' + headers: + Host: + - clients2.google.com + Proxy-Connection: + - keep-alive + Pragma: + - no-cache + Cache-Control: + - no-cache + User-Agent: + - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, + like Gecko) HeadlessChrome/135.0.0.0 Safari/537.36 + Accept-Encoding: + - '' + Connection: + - close + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + X-Content-Type-Options: + - nosniff + X-Cup-Server-Proof: + - 3046022100fba38f7a7931382e1cb54a56b47df618bf5ff41256e68b26c065c91b6045cfcd022100f2716eb5ef7a4a79ab29793f611a14eca20169e26f997721c6f1f09a41c631bc:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - Mon, 01 Jan 1990 00:00:00 GMT + Date: + - Thu, 17 Apr 2025 17:03:35 GMT + Content-Disposition: + - attachment; filename="json.txt"; filename*=UTF-8''json.txt + Cross-Origin-Resource-Policy: + - same-site + Cross-Origin-Opener-Policy: + - same-origin + Server: + - ESF + X-Xss-Protection: + - '0' + X-Frame-Options: + - SAMEORIGIN + Accept-Ranges: + - none + Vary: + - Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site,Accept-Encoding + Connection: + - close + Transfer-Encoding: + - chunked + body: + encoding: UTF-8 + string: |- + )]}' + {"current_time_millis":1744909415303,"server_nonce":-2.9029924837530115E15} + recorded_at: Thu, 17 Apr 2025 17:03:35 GMT +- request: + method: post + uri: https://accounts.google.com/ListAccounts?gpsia=1&json=standard&source=ChromiumBrowser + body: + encoding: UTF-8 + string: " " + headers: + Host: + - accounts.google.com + Connection: + - close + Content-Length: + - '1' + Origin: + - https://www.google.com + Content-Type: + - application/x-www-form-urlencoded + Sec-Fetch-Site: + - none + Sec-Fetch-Mode: + - no-cors + Sec-Fetch-Dest: + - empty + User-Agent: + - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, + like Gecko) HeadlessChrome/135.0.0.0 Safari/537.36 + Accept-Encoding: + - '' + Accept-Language: + - en-US,en;q=0.9 + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + Access-Control-Allow-Origin: + - https://www.google.com + Access-Control-Allow-Credentials: + - 'true' + X-Content-Type-Options: + - nosniff + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Pragma: + - no-cache + Expires: + - Mon, 01 Jan 1990 00:00:00 GMT + Date: + - Thu, 17 Apr 2025 17:03:35 GMT + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + Permissions-Policy: + - ch-ua-arch=*, ch-ua-bitness=*, ch-ua-full-version=*, ch-ua-full-version-list=*, + ch-ua-model=*, ch-ua-wow64=*, ch-ua-form-factors=*, ch-ua-platform=*, ch-ua-platform-version=* + Cross-Origin-Opener-Policy: + - same-origin + Accept-Ch: + - Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Full-Version, Sec-CH-UA-Full-Version-List, + Sec-CH-UA-Model, Sec-CH-UA-WoW64, Sec-CH-UA-Form-Factors, Sec-CH-UA-Platform, + Sec-CH-UA-Platform-Version + Content-Security-Policy: + - require-trusted-types-for 'script';report-uri /_/IdentityListAccountsHttp/cspreport + - script-src 'report-sample' 'nonce-UUjSaJNggtYuUg6IXxY3Ow' 'unsafe-inline';object-src + 'none';base-uri 'self';report-uri /_/IdentityListAccountsHttp/cspreport;worker-src + 'self' + - 'script-src ''unsafe-inline'' ''unsafe-eval'' blob: data: ''self'' https://apis.google.com + https://ssl.gstatic.com https://www.google.com https://www.googletagmanager.com + https://www.gstatic.com https://www.google-analytics.com;report-uri /_/IdentityListAccountsHttp/cspreport/allowlist' + - 'script-src ''unsafe-inline'' ''unsafe-eval'' blob: data:;report-uri /_/IdentityListAccountsHttp/cspreport/fine-allowlist' + Reporting-Endpoints: + - default="/_/IdentityListAccountsHttp/web-reports?context=eJzjEtHikmJw0JBiOHxtB5Meyy0mIyAW4uF4_qLlAJvAiVPTzjAq6SblF8ZnpqTmlWSWVOZkFpckJifnl-aVFBenFpWlFsUbGRiZGpgYmOkZWMQXGAAAeKIcOg" + Server: + - ESF + X-Xss-Protection: + - '0' + Alt-Svc: + - h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 + Accept-Ranges: + - none + Vary: + - Origin,Accept-Encoding + Connection: + - close + Transfer-Encoding: + - chunked + body: + encoding: UTF-8 + string: '["gaia.l.a.r",[]]' + recorded_at: Thu, 17 Apr 2025 17:03:35 GMT +- request: + method: get + uri: https://sandbox.getpinwheel.com/v1/search?q=foo&supported_jobs=paystubs + body: + encoding: US-ASCII + string: '' + headers: + Content-Type: + - application/json + Pinwheel-Version: + - '2023-11-22' + X-Api-Secret: + - "" + User-Agent: + - Faraday v2.9.2 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 17 Apr 2025 17:03:38 GMT + Content-Type: + - application/json + Content-Length: + - '13405' + Connection: + - keep-alive + Server: + - uvicorn + Pinwheel-Version: + - '2023-11-22' + Content-Security-Policy: + - frame-ancestors 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; + X-Pinwheel-Request-Id: + - 9134d1d7-ad8e-4326-ad29-74ff50ea551f + body: + encoding: UTF-8 + string: '{"meta":{"count":25},"data":[{"id":"5a8cfb92-3373-4e65-b41b-54e821e79671","name":"McKee + Foods","platform_type":"payroll","last_updated":"2024-11-07T17:01:54.781450+00:00","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/McKee%20Foods.png","supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"bc507614-8b07-41b6-a00c-daa0d2890350","name":"Tyson + Foods","platform_type":"payroll","last_updated":"2023-08-22T20:06:41.070099+00:00","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Tyson%20Foods.png","supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":false},{"id":"bf323346-3eb2-4aff-8db4-aba727f88768","name":"Wakefern + Food Corporation","platform_type":"payroll","last_updated":"2022-10-07T17:28:52.736273+00:00","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Wakefern%20Food%20Corporation.jpeg","supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":false,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":false},{"id":"ccfe6b12-f4ab-449d-af38-78e88bdc432c","name":"Food + 4 Less","platform_type":"payroll","last_updated":"2023-06-13T16:05:06.555758+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"ed8e8c70-9650-43dd-bba4-bec9b23b0f32","name":"Food + Depot","platform_type":"payroll","last_updated":"2024-11-21T20:24:05.298129+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"41e23a45-bdf9-47ea-ab94-303c19de7ff2","name":"Foods + Co.","platform_type":"payroll","last_updated":"2023-06-13T16:05:06.555758+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"73fb1dae-7e5f-4e5b-86a0-ace234351439","name":"76 + Gas Station & Food Mart","platform_type":"payroll","last_updated":"2024-01-16T17:19:29.270713+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"715486cb-54a4-4f17-a4a8-5466245b7605","name":"AVI + Foodsystems","platform_type":"payroll","last_updated":"2024-01-16T17:19:29.270713+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"8655f036-9b70-4faa-a415-32377fc5cef7","name":"American + Dehydrated Foods, LLC","platform_type":"payroll","last_updated":"2024-11-01T15:26:32.374781+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","company_paystubs","company_employments","direct_deposit_switch","paystubs","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"260143e7-0866-44cd-a795-0bf9c15ca175","name":"Be + Worthy Foods","platform_type":"payroll","last_updated":"2024-01-16T17:19:29.270713+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_census","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":false},{"id":"4ae15949-d1f4-40c9-96d2-e12a0996f7ed","name":"Blue + Line Foodservice Distribution","platform_type":"payroll","last_updated":"2025-02-13T21:55:20.274906+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"c1c25cc0-6f0c-428a-8243-d7e28287125f","name":"Border + Foods","platform_type":"payroll","last_updated":"2025-03-19T23:19:22.707781+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"4943e082-dbe7-4732-8c42-9ac16a1e210a","name":"Bottom + Dollar Food","platform_type":"payroll","last_updated":"2023-02-16T15:47:02.914404+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":false},{"id":"abba5280-bdbf-47a5-bb2b-a05779641e39","name":"Charter + Foods Inc","platform_type":"payroll","last_updated":"2024-11-21T21:21:03.780802+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":false},{"id":"3449a450-a3b5-4d56-80c1-c05d447c5e53","name":"ConAgra + Foods Packaged Foods","platform_type":"payroll","last_updated":"2025-02-13T22:10:27.819739+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"35883773-5d90-4d35-8444-f46683231d80","name":"Cotti + Foods Corporation","platform_type":"payroll","last_updated":"2024-01-16T17:19:29.270713+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"014fafe8-03b0-44ca-982e-4b76e9dc0c93","name":"Crocs + Footwear","platform_type":"payroll","last_updated":"2024-01-16T17:19:29.270713+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"cfe01d72-eca9-4fa4-b407-1e00620158ca","name":"DN-Angel + Food-Hells Kitchen","platform_type":"payroll","last_updated":"2025-02-13T22:19:46.215106+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"c2aa7627-5250-43b4-aaf0-361c9f4e162c","name":"FPL + Food LLC","platform_type":"payroll","last_updated":"2024-01-16T17:19:29.270713+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"c2d92f7d-3c5b-4ba2-b669-650c1f283d86","name":"Fourteen + Foods","platform_type":"payroll","last_updated":"2025-03-19T23:19:22.707781+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"c6159d2f-1fba-4566-b04d-667769776104","name":"Georgia + Foods Llc","platform_type":"payroll","last_updated":"2023-10-27T15:06:31.448680+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"c572567f-7fa4-4210-b32b-87a213765b11","name":"Giant + Food Stores Supermarket & Pharmacy","platform_type":"payroll","last_updated":"2023-09-25T19:42:01.220598+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":false},{"id":"92767427-8613-46ff-843e-c64d925916e8","name":"Gordon + Food Service","platform_type":"payroll","last_updated":"2024-11-07T17:01:54.781450+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"615b482b-fad8-466e-9bb6-0a6817b3d047","name":"Gordon + Food Service Store","platform_type":"payroll","last_updated":"2024-10-29T19:02:18.906169+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_incomes","income","identity","employment"],"fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true},{"id":"dda6a6ef-2985-4148-9d44-bf39b41da86b","name":"Haza + Foods Of Northeast, Llc","platform_type":"payroll","last_updated":"2024-11-07T22:07:02.678082+00:00","logo_url":null,"supported_jobs":["shifts","direct_deposit_allocations","tax_forms","direct_deposit_switch","paystubs","company_employments","company_incomes","company_census","income","identity","employment"],"fractional_amount_supported":true,"amount_supported":true,"min_amount":null,"max_amount":null,"response_type":"employer","min_percentage":1,"max_percentage":99,"percentage_supported":true}]}' + recorded_at: Thu, 17 Apr 2025 17:03:38 GMT +- request: + method: post + uri: https://sandbox.getpinwheel.com/v1/link_tokens + body: + encoding: UTF-8 + string: '{"org_name":"SNAP Income Pilot","required_jobs":["paystubs"],"end_user_id":"f0a9a6e9-6d36-44ec-97e0-9ea371de772f","skip_intro_screen":true,"language":"en","employer_id":"5a8cfb92-3373-4e65-b41b-54e821e79671"}' + headers: + Content-Type: + - application/json + Pinwheel-Version: + - '2023-11-22' + X-Api-Secret: + - "" + User-Agent: + - Faraday v2.9.2 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 17 Apr 2025 17:03:38 GMT + Content-Type: + - application/json + Content-Length: + - '1730' + Connection: + - keep-alive + Server: + - uvicorn + Pinwheel-Version: + - '2023-11-22' + Content-Security-Policy: + - frame-ancestors 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; + X-Pinwheel-Request-Id: + - ea269b44-4907-48d5-aca3-13b8af1779c7 + body: + encoding: UTF-8 + string: '{"data":{"mode":"sandbox","id":"390e640f-98c7-4a19-b016-a55428a51b62","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InJlcXVpcmVkX2pvYnMiOlsicGF5c3R1YnMiXSwib3JnX25hbWUiOiJTTkFQIEluY29tZSBQaWxvdCIsImFsbG9jYXRpb24iOm51bGwsInBsYXRmb3JtX2tleSI6bnVsbCwic2tpcF9pbnRyb19zY3JlZW4iOnRydWUsInNraXBfZXhpdF9zdXJ2ZXkiOmZhbHNlLCJlbXBsb3llcl9pZCI6IjVhOGNmYjkyLTMzNzMtNGU2NS1iNDFiLTU0ZTgyMWU3OTY3MSIsImRpc2FibGVfZGlyZWN0X2RlcG9zaXRfc3BsaXR0aW5nIjpmYWxzZSwicGxhdGZvcm1faWQiOm51bGwsInNraXBfZGVwb3NpdF9jb25maXJtYXRpb24iOm51bGwsInBsYXRmb3JtX3R5cGUiOm51bGwsImxhbmd1YWdlIjoiZW4iLCJlbmRfdXNlcl9pZCI6ImYwYTlhNmU5LTZkMzYtNDRlYy05N2UwLTllYTM3MWRlNzcyZiIsImFjY291bnRfaWQiOm51bGwsImRvY3VtZW50X3VwbG9hZHMiOm51bGwsImVuYWJsZV9jYXJkX3N3aXRjaCI6ZmFsc2UsInNtYXJ0X2JyYW5jaCI6bnVsbCwiZW5hYmxlX3VzZXJfaW5wdXRfYmFua19pbmZvIjpmYWxzZSwidGFncyI6bnVsbCwiY29tcGFueV9jb25uZWN0IjpudWxsLCJkZXBvc2l0X2Zvcm1zIjoiZGlzYWJsZWQiLCJlbmRfdXNlciI6bnVsbCwiaGFzX3VzZXJfYXV0aGVudGljYXRpb25fZGF0YSI6ZmFsc2UsImhhc19lbnJfcGlpIjpmYWxzZSwiZW5jcnlwdGVkX2pzb24iOm51bGwsImVuY3J5cHRpb25fZW52ZWxvcGUiOm51bGwsImVuYWJsZV9iaWxsX25hdmlnYXRvciI6ZmFsc2UsImNhcmRzIjpudWxsLCJtaXNzaW5nX3VzZXJfYXV0aGVudGljYXRpb25fZmllbGRzIjpudWxsLCJlbmFibGVfc2VsZl9pZCI6ZmFsc2UsIm1vZGUiOiJzYW5kYm94IiwiYXBpX2tleSI6ImZha2VhcGkiLCJ0b2tlbl9pZCI6IjM5MGU2NDBmLTk4YzctNGExOS1iMDE2LWE1NTQyOGE1MWI2MiIsImpvYiI6InBheXN0dWJzIiwiX3VpZCI6IjZhYjMyMDAwLTJiMTUtNDcyNy04MzRmLTM0MzhmYjFjZWUxNyIsIndvcmtzcGFjZV9uYW1lIjoiTmF2YSBQQkMiLCJ3b3Jrc3BhY2VfdHlwZSI6ImNsaWVudCIsImhvbWVyX3VybCI6bnVsbH0sImlhdCI6MTc0NDkwOTQxOCwiZXhwIjoxNzQ0OTEzMDE4fQ.PYChVGzPVBpMYJHVZ3r6sFOmuzdM5jFBksLYmNEcypU","smart_branch_url":null,"expires":"2025-04-17T18:03:38.764146+00:00"}}' + recorded_at: Thu, 17 Apr 2025 17:03:38 GMT +- request: + method: get + uri: https://sandbox.getpinwheel.com/v1/platforms/5965580e-380f-4b86-8a8a-7278c77f73cb + body: + encoding: US-ASCII + string: '' + headers: + Content-Type: + - application/json + Pinwheel-Version: + - '2023-11-22' + X-Api-Secret: + - "" + User-Agent: + - Faraday v2.9.2 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 17 Apr 2025 17:03:42 GMT + Content-Type: + - application/json + Content-Length: + - '576' + Connection: + - keep-alive + Server: + - uvicorn + Pinwheel-Version: + - '2023-11-22' + Content-Security-Policy: + - frame-ancestors 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; + X-Pinwheel-Request-Id: + - a290c30f-69e7-4dbf-8c62-1941ed836dd1 + body: + encoding: UTF-8 + string: '{"data":{"id":"5965580e-380f-4b86-8a8a-7278c77f73cb","name":"Workday","type":"payroll","fractional_amount_supported":false,"min_amount":null,"max_amount":null,"last_updated":"2024-10-04T21:31:31.481595+00:00","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/cfmpw.png","percentage_supported":true,"min_percentage":1,"max_percentage":99,"supported_jobs":["shifts","company_incomes","tax_forms","company_census","income","paystubs","company_employments","employment","identity","direct_deposit_switch","direct_deposit_allocations"],"amount_supported":true}}' + recorded_at: Thu, 17 Apr 2025 17:03:42 GMT +- request: + method: delete + uri: https://sandbox.getpinwheel.com/v1/webhooks/e18da643-c900-4b51-948e-0b7629f5e4cf + body: + encoding: US-ASCII + string: '' + headers: + Content-Type: + - application/json + Pinwheel-Version: + - '2023-11-22' + X-Api-Secret: + - "" + User-Agent: + - Faraday v2.9.2 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Thu, 17 Apr 2025 17:03:43 GMT + Content-Type: + - application/json + Content-Length: + - '2' + Connection: + - keep-alive + Server: + - uvicorn + Pinwheel-Version: + - '2023-11-22' + Content-Security-Policy: + - frame-ancestors 'none' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; + X-Pinwheel-Request-Id: + - 7d00a5d2-6b87-4c7c-b0ca-b34484b5ae1f + body: + encoding: UTF-8 + string: "{}" + recorded_at: Thu, 17 Apr 2025 17:03:43 GMT +recorded_with: VCR 6.3.1 diff --git a/app/spec/rails_helper.rb b/app/spec/rails_helper.rb index 1b806e9f3..ab99c8716 100644 --- a/app/spec/rails_helper.rb +++ b/app/spec/rails_helper.rb @@ -39,7 +39,57 @@ puts e.to_s.strip exit 1 end + +VCR.configure do |config| + config.cassette_library_dir = "spec/fixtures/vcr_cassettes" + config.hook_into :webmock + config.ignore_request do |request| + request.uri.include?("http://127.0.0.1") + end + config.ignore_hosts '127.0.0.1', 'localhost', 'logs.browser-intake-datadoghq.com', "firefox-settings-attachments.cdn.mozilla.net", + "firefox.settings.services.mozilla.com", "plugin.argyle.com", "switchboard.pwhq.net", "passwordsleakcheck-pa.googleapis.com", + "optimizationguide-pa.googleapis.com ", + "cdn.getpinwheel.com", "featuregates.org", "datadog", "events.statsigapi.net", "content-signature-2.cdn.mozilla.net", "content-autofill.googleapis.com" + config.default_cassette_options = { record: :once } + config.filter_sensitive_data("") { ENV["PINWHEEL_API_TOKEN_SANDBOX"] } +end + +def json_extract(json) + begin + JSON.parse(json) + rescue Exception => e + nil + end +end + +require 'billy/capybara/rspec' + +Billy.configure do |c| + c.cache = true + c.persist_cache = true + c.cache_path = 'spec/req_cache/' + # c.non_whitelisted_requests_disabled = true + c.whitelist << /cdn\.getpinwheel\.com/ + c.whitelist << /mozilla\./ + c.whitelist << /plugin\.argyle\.com/ + c.whitelist << /statsigapi/ + c.whitelist << /featuregates/ + c.whitelist << /switchboard/ + c.whitelist << /datadog/ + c.whitelist << /cloudinary/ + c.whitelist << /googleapis/ + c.whitelist << /google\.com/ +end +Billy.proxy.restore_cache + RSpec.configure do |config| + config.before(:each, type: :feature) do + Capybara.current_driver = :selenium_chrome_headless_billy + end + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + # Include a handful of useful helpers we've written config.include TestHelpers @@ -48,6 +98,13 @@ # instead of true. config.use_transactional_fixtures = true + config.around(:each, :vcr) do |example| + vcr_metadata = example.metadata.dig(:vcr) + VCR.use_cassette(vcr_metadata[:name], record: vcr_metadata[:record]) do + example.call + end + end + # You can uncomment this line to turn off ActiveRecord support entirely. # config.use_active_record = false diff --git a/app/spec/req_cache/get_api.getpinwheel.com_02620475cc6b3ccb5b80ab06426229fdbfcba952.yml b/app/spec/req_cache/get_api.getpinwheel.com_02620475cc6b3ccb5b80ab06426229fdbfcba952.yml new file mode 100644 index 000000000..a792c7a65 --- /dev/null +++ b/app/spec/req_cache/get_api.getpinwheel.com_02620475cc6b3ccb5b80ab06426229fdbfcba952.yml @@ -0,0 +1,17 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744148823325 +:body: '' +:status: 200 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:47:04 GMT + Content-Type: application/json + Content-Length: '111' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: fb380891-cad9-4a39-ac14-5f2a426f772d + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"response_type":"success","account_id":"ca9d7ef6-c3d6-4a86-8bd9-d495a732d03a","masked_accounts":null}}' diff --git a/app/spec/req_cache/get_api.getpinwheel.com_60faddcff6f8cec964bb23f295aecc3e7415a8d8.yml b/app/spec/req_cache/get_api.getpinwheel.com_60faddcff6f8cec964bb23f295aecc3e7415a8d8.yml new file mode 100644 index 000000000..e22c6659c --- /dev/null +++ b/app/spec/req_cache/get_api.getpinwheel.com_60faddcff6f8cec964bb23f295aecc3e7415a8d8.yml @@ -0,0 +1,17 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744148819510 +:body: '' +:status: 200 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:47:00 GMT + Content-Type: application/json + Content-Length: '68' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: ecc76177-2680-41af-8d0e-e5b9d4ecefea + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"response_type":"processing","title":null,"subtitle":null}}' diff --git a/app/spec/req_cache/get_api.getpinwheel.com_9f2d3c63d14cf18a6c45b7718c03ae34349fe5a9.yml b/app/spec/req_cache/get_api.getpinwheel.com_9f2d3c63d14cf18a6c45b7718c03ae34349fe5a9.yml new file mode 100644 index 000000000..c12eae633 --- /dev/null +++ b/app/spec/req_cache/get_api.getpinwheel.com_9f2d3c63d14cf18a6c45b7718c03ae34349fe5a9.yml @@ -0,0 +1,18 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744148821056 +:body: '' +:status: 200 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:47:02 GMT + Content-Type: application/json + Content-Length: '749' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: 42c2d2e7-4368-42cb-bbce-9e657bc993a3 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"response_type":"next","template":{"template_type":"form","fields":[{"key":"username","field_type":"text","field_subtype":"plaintext","label":"Username","locked_field":false,"min_length":null,"max_length":null,"pattern":null,"placeholder":null,"options":null,"payload":null,"hint":null,"initial_value":null,"should_obfuscate":false},{"key":"password","field_type":"text","field_subtype":"password","label":"Password","locked_field":false,"min_length":null,"max_length":null,"pattern":null,"placeholder":null,"options":null,"payload":null,"hint":null,"initial_value":null,"should_obfuscate":true}],"title":"Log + into your payroll account","subtitle":"Enter your login credentials to continue","text_list":[],"actions":[],"button_text":null}}}' diff --git a/app/spec/req_cache/get_api.getpinwheel.com_ca21df78bbec0919996e2b8b4a0a63c2c1878b0f.yml b/app/spec/req_cache/get_api.getpinwheel.com_ca21df78bbec0919996e2b8b4a0a63c2c1878b0f.yml new file mode 100644 index 000000000..877bb11a2 --- /dev/null +++ b/app/spec/req_cache/get_api.getpinwheel.com_ca21df78bbec0919996e2b8b4a0a63c2c1878b0f.yml @@ -0,0 +1,18 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744149038744 +:body: '' +:status: 400 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:50:39 GMT + Content-Type: application/json + Content-Length: '151' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: 30e8bee9-da4e-4cac-a571-4bd3b8cdcd63 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"error":{"type":"RECORD_NOT_FOUND","code":"NO_ACTIVE_SESSION_FOUND","status_code":400,"message":"There + is not an active session for this link token"}}' diff --git a/app/spec/req_cache/get_api.getpinwheel.com_d45185aa271b3ae26515fbd0127e92685742ded0.yml b/app/spec/req_cache/get_api.getpinwheel.com_d45185aa271b3ae26515fbd0127e92685742ded0.yml new file mode 100644 index 000000000..5ff95d7b8 --- /dev/null +++ b/app/spec/req_cache/get_api.getpinwheel.com_d45185aa271b3ae26515fbd0127e92685742ded0.yml @@ -0,0 +1,18 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/initialization_context/?employer_id=5a8cfb92-3373-4e65-b41b-54e821e79671 +:body: '' +:status: 200 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:46:56 GMT + Content-Type: application/json + Content-Length: '3267' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: c8966505-b7e3-42ed-8363-b44f4c5556c0 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"platform":{"id":"5965580e-380f-4b86-8a8a-7278c77f73cb","name":"Workday","fractional_amount_supported":false,"amount_supported":true,"min_amount":null,"max_amount":null,"last_updated":"2024-10-04T21:31:31.481595+00:00","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/cfmpw.png","supported_jobs":[{"job":"direct_deposit_payment","enabled":true,"id":"e9b4088a-5f45-4f46-a868-8126e0235ba0"},{"job":"direct_deposit_switch","enabled":true,"id":"6d7c69ec-998a-48de-83f1-a7dfee0bde2f"},{"job":"employment","enabled":true,"id":"978040ad-1206-461a-bc53-c2628a2d483c"},{"job":"paystubs","enabled":true,"id":"2796f212-8ab3-4bf7-81cc-5f94369b08ba"},{"job":"identity","enabled":true,"id":"82905309-3e87-45d6-80ff-f382b610356d"},{"job":"income","enabled":true,"id":"38c894d4-345a-4f3b-99f6-e3adee8d3bcd"},{"job":"direct_deposit_allocations","enabled":true,"id":"ddc59a31-173b-4c87-a370-e916c82c9591"},{"job":"tax_forms","enabled":true,"id":"a1d1d45b-a63d-4e1b-bb66-603e9b4cdfb2"},{"job":"company_incomes","enabled":true,"id":"bd30d10c-c049-4788-8024-e45740b6e33b"},{"job":"company_employments","enabled":true,"id":"55a97722-8dde-4c4e-8def-b902e8107c54"},{"job":"company_census","enabled":true,"id":"2d771258-19d2-4b11-a2bf-1b44d728d6af"}],"type":"payroll","percentage_supported":true,"min_percentage":1,"max_percentage":99,"full_switch_supported":true,"key":"cfmpw","is_employer":false,"is_login_only":false,"picker_logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/picker/cfmpw.png","logo_height":null,"search_logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/cfmpw.png","primary_color":"#1170FF","supports_auto_reauth":false,"supports_session_ping":true,"allow_automated_updates":true,"default_guided_switch":false,"provider_confirmation_type":"unbounded_list","provider_confirmation_subtype":"parent_platform"},"employer":{"id":"5a8cfb92-3373-4e65-b41b-54e821e79671","name":"McKee + Foods","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/McKee%20Foods.png","enabled":true,"last_updated":"2024-11-07T17:01:54.781450+00:00","created_at":"2020-11-11T23:07:44.074017+00:00","mapping_source":"PUBLIC_RESEARCH","min_percentage":1,"max_percentage":99,"percentage_supported":true,"supported_jobs":[{"job":"direct_deposit_payment","enabled":true,"id":"e9b4088a-5f45-4f46-a868-8126e0235ba0"},{"job":"direct_deposit_switch","enabled":true,"id":"6d7c69ec-998a-48de-83f1-a7dfee0bde2f"},{"job":"employment","enabled":true,"id":"978040ad-1206-461a-bc53-c2628a2d483c"},{"job":"paystubs","enabled":true,"id":"2796f212-8ab3-4bf7-81cc-5f94369b08ba"},{"job":"identity","enabled":true,"id":"82905309-3e87-45d6-80ff-f382b610356d"},{"job":"income","enabled":true,"id":"38c894d4-345a-4f3b-99f6-e3adee8d3bcd"},{"job":"direct_deposit_allocations","enabled":true,"id":"ddc59a31-173b-4c87-a370-e916c82c9591"},{"job":"tax_forms","enabled":true,"id":"a1d1d45b-a63d-4e1b-bb66-603e9b4cdfb2"},{"job":"company_incomes","enabled":true,"id":"bd30d10c-c049-4788-8024-e45740b6e33b"},{"job":"company_employments","enabled":true,"id":"55a97722-8dde-4c4e-8def-b902e8107c54"},{"job":"company_census","enabled":true,"id":"2d771258-19d2-4b11-a2bf-1b44d728d6af"}],"provider_confirmation_type":null,"provider_confirmation_subtype":null},"public_key":null}}' diff --git a/app/spec/req_cache/get_sandbox.getpinwheel.com_22882c5a8e22b9679ce42f01fe05bc0a7e0e72e7.yml b/app/spec/req_cache/get_sandbox.getpinwheel.com_22882c5a8e22b9679ce42f01fe05bc0a7e0e72e7.yml new file mode 100644 index 000000000..5525cf3b7 --- /dev/null +++ b/app/spec/req_cache/get_sandbox.getpinwheel.com_22882c5a8e22b9679ce42f01fe05bc0a7e0e72e7.yml @@ -0,0 +1,56 @@ +--- +:scope: +:url: https://sandbox.getpinwheel.com/v1/ui/initial_providers +:body: '' +:status: 200 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:46:56 GMT + Content-Type: application/json + Content-Length: '29082' + Connection: close + server: uvicorn + access-control-allow-origin: "*" + content-security-policy: frame-ancestors 'none' + strict-transport-security: max-age=31536000; includeSubDomains; + x-pinwheel-request-id: efd5020e-dc03-42c6-826a-d6348fa5f306 +:content: '{"data":{"popular":[{"id":"5becff90-1e35-450a-8995-13ac411e749b","name":"ADP","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/adpPortal.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"5965580e-380f-4b86-8a8a-7278c77f73cb","name":"Workday","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/cfmpw.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"d66e65b2-536d-4b2d-b73c-f6addd66c0f4","name":"Amazon","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Amazon.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"1d6207d3-7bf0-4a1c-99f5-82af61572775","name":"Walmart","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Walmart.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"737d833a-1b68-44f7-92ae-3808374cb459","name":"DoorDash + (Dasher)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/DoorDash%20%28Dasher%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"3f812c04-ac83-495b-99ca-7ec7d56dc68b","name":"Paycom","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paycom.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"9a4e213b-aeed-4cb2-aace-696bcd2b1e0d","name":"Paychex + Flex","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paychex.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"72b4ffdc-dfd5-44ee-8a3a-b1acb92ce188","name":"McDonald''s","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/McDonalds%20%28Corporate%20employees%20only%29.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"913170d1-393c-4f35-8c23-df3133ce7529","name":"Paylocity","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paylocity.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b0b655f8-4ae6-4d09-a60f-1df9a2a1fd16","name":"Paycor","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paycor.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"a6512ce4-d9ca-4113-b732-39c363520a83","name":"UKG + Pro (a.k.a. Ultipro)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/ukgPro.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"91063607-2b4a-4c8e-8045-a543f01b8b09","name":"Uber + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Uber%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"cace440e-43f7-46b4-a937-063f7ed22b74","name":"Uber + Eats (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Uber%20Eats%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"a2151677-2920-487a-a63c-2fbef3122c10","name":"MyPay","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/MyPay.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"065d66be-2bc7-4c79-9365-1eb1e12d879b","name":"My + Epp","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/My%20Epp.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"0c271780-fd19-43e0-a721-89228bb5fc5e","name":"Ceridian + Dayforce","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/ceridian.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0e22141d-9ad8-46ee-94d3-ab77b95aceba","name":"Home + Depot","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Home%20Depot.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"70b2bed2-ada8-49ec-99c2-691cc7d28df6","name":"Lyft + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Lyft%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"165f617a-31d5-4cc4-9495-8304e049ba2f","name":"UPS","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/United%20Parcel%20Service.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"5e55be4d-0393-4e64-928d-e24f2bea80fd","name":"Target","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Target.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"eec356b5-9338-4c7c-ac95-b5fdb2213633","name":"Amazon + Flex","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Amazon%20Flex.png","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"dd65fb10-88c3-47c0-9eee-fbb17bb4f1cb","name":"Dollar + General","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Dollar%20General.png","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b7af52b7-e610-4a97-9342-dc39163ca2df","name":"Kroger","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Kroger.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"59595148-c2b4-4bc7-8b1e-9d0d36587b67","name":"Lowe''s","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Lowe%27s.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"4475fef1-018d-43b8-92cb-bd548f8fd278","name":"Gusto","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/gusto.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0ba48840-899b-4e23-9429-9456094bf1f1","name":"Circle + K","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Circle%20K.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"d02a6913-f0b3-4cf3-acfa-a05fa0646261","name":"GrubHub + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/GrubHub%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"90c532eb-ddde-4f1c-8379-7d2a4d8d90e7","name":"Chipotle","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Chipotle.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"fcc2be7d-af09-4d2e-b938-f4ccd3de3fb4","name":"OnlyFans","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/OnlyFans.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false}],"employers":[{"id":"1d6207d3-7bf0-4a1c-99f5-82af61572775","name":"Walmart","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Walmart.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"d66e65b2-536d-4b2d-b73c-f6addd66c0f4","name":"Amazon","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Amazon.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"165f617a-31d5-4cc4-9495-8304e049ba2f","name":"UPS","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/United%20Parcel%20Service.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"5e55be4d-0393-4e64-928d-e24f2bea80fd","name":"Target","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Target.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"dd65fb10-88c3-47c0-9eee-fbb17bb4f1cb","name":"Dollar + General","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Dollar%20General.png","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b7af52b7-e610-4a97-9342-dc39163ca2df","name":"Kroger","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Kroger.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0e22141d-9ad8-46ee-94d3-ab77b95aceba","name":"Home + Depot","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Home%20Depot.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"59595148-c2b4-4bc7-8b1e-9d0d36587b67","name":"Lowe''s","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Lowe%27s.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0ba48840-899b-4e23-9429-9456094bf1f1","name":"Circle + K","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Circle%20K.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"90c532eb-ddde-4f1c-8379-7d2a4d8d90e7","name":"Chipotle","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Chipotle.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"97d53b3c-0cef-44ee-be90-1a3a7973d719","name":"Macy''s","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Macy%27s.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b801f397-98a9-4a71-a3af-6b7760403487","name":"Darden + Restaurants","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Darden%20Restaurants.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b928719f-533c-4fcf-bbc5-e62d6defa61a","name":"CVS + Health","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/CVS%20Health.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"72b4ffdc-dfd5-44ee-8a3a-b1acb92ce188","name":"McDonald''s","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/McDonalds%20%28Corporate%20employees%20only%29.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"220f3b99-d489-4376-ba1c-6cee39cc5fdc","name":"Publix","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Publix.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"af1dcac4-a934-4efa-99a8-7cfd14e53090","name":"Ahold + Delhaize","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Ahold%20Delhaize.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"453223da-2006-4f59-843a-15ca597f372e","name":"AT&T","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/AT%26T.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"6cac3ecd-cef3-4e03-bfe1-a04c28e58bdd","name":"Waffle + House","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Waffle%20House.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"dbab372d-1e72-4ce1-beb7-3daac806a20a","name":"Albertsons","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Albertsons.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"9f081e33-3881-4c54-8a17-cd35e35eb73d","name":"Auto + Zone","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Autozone.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"d4568c30-a4ae-4b83-a691-c612b200d5b1","name":"Best + Buy","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Best%20Buy.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"e5aa352c-4fa5-491f-b457-4118cc2d8d56","name":"Panera + Bread","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Panera%20Bread.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false}],"gigs":[{"id":"737d833a-1b68-44f7-92ae-3808374cb459","name":"DoorDash + (Dasher)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/DoorDash%20%28Dasher%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"91063607-2b4a-4c8e-8045-a543f01b8b09","name":"Uber + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Uber%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"cace440e-43f7-46b4-a937-063f7ed22b74","name":"Uber + Eats (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Uber%20Eats%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"70b2bed2-ada8-49ec-99c2-691cc7d28df6","name":"Lyft + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Lyft%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"eec356b5-9338-4c7c-ac95-b5fdb2213633","name":"Amazon + Flex","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Amazon%20Flex.png","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"d02a6913-f0b3-4cf3-acfa-a05fa0646261","name":"GrubHub + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/GrubHub%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"9f7ddcaf-cbc5-4bd2-b701-d40c67389eae","name":"Instacart + (Full Service Shopper)","platform_type":"payroll","logo_url":null,"response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"fcc2be7d-af09-4d2e-b938-f4ccd3de3fb4","name":"OnlyFans","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/OnlyFans.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"f5e466a5-b5cc-4895-8a17-002cfcdf1e1e","name":"Roadie","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Roadie.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"337624e6-3f15-4b9f-a44a-f7422901f6a5","name":"Poshmark + (Seller)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Poshmark%20%28Seller%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"5b2db392-791e-4dbc-a000-321a79d557ab","name":"Wonolo","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Wonolo.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"adde7178-43cd-4cc6-8857-65dfc54a77e8","name":"TaskRabbit","platform_type":"payroll","logo_url":null,"response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false}],"platforms":[{"id":"5becff90-1e35-450a-8995-13ac411e749b","name":"ADP","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/adpPortal.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"5965580e-380f-4b86-8a8a-7278c77f73cb","name":"Workday","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/cfmpw.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"3f812c04-ac83-495b-99ca-7ec7d56dc68b","name":"Paycom","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paycom.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"9a4e213b-aeed-4cb2-aace-696bcd2b1e0d","name":"Paychex + Flex","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paychex.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"913170d1-393c-4f35-8c23-df3133ce7529","name":"Paylocity","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paylocity.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b0b655f8-4ae6-4d09-a60f-1df9a2a1fd16","name":"Paycor","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paycor.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0c271780-fd19-43e0-a721-89228bb5fc5e","name":"Ceridian + Dayforce","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/ceridian.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"a6512ce4-d9ca-4113-b732-39c363520a83","name":"UKG + Pro (a.k.a. Ultipro)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/ukgPro.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"4475fef1-018d-43b8-92cb-bd548f8fd278","name":"Gusto","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/gusto.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0570d9a5-b937-4005-9278-deb164ff4940","name":"Alliance + HCM","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/hrAlliance.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"a2151677-2920-487a-a63c-2fbef3122c10","name":"MyPay","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/MyPay.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"065d66be-2bc7-4c79-9365-1eb1e12d879b","name":"My + Epp","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/My%20Epp.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"966f1269-a1ec-401a-89bd-a91e2c5ca27d","name":"Proliant","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/proliant.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"e56f88dd-9e4b-4744-a5f3-ea30649d7ba8","name":"TriNet","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/trinet.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"ece98816-5aa3-4654-95f9-b3a752f7cc5c","name":"Rippling","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/rippling.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"f5a8f361-8a16-4cfa-b13d-440f2f879608","name":"Netchex","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/netchex.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"5fc8234b-e80e-4a1c-aac3-c0a432e7242b","name":"Insperity","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/insperity.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"2303bd92-4919-4c01-b9ab-4879f8041801","name":"Justworks","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/justworks.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"da11ffa0-947c-4a9b-8e23-163a5dfe0ca6","name":"Zenefits","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/zenefits.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"ea4ec153-cb78-4e41-b1fe-b52280fddeb2","name":"Paychex + Oasis","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/oasisBatch.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"26077b62-d8ae-4766-b943-dba9f870ac1f","name":"Viventium","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/viventium.jpeg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"9d8415cd-792c-42cb-bc1e-bf369b80002a","name":"Toast","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/toast.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"f1b5b8e9-a414-44bb-b6ab-01337f7cb02a","name":"QuickBooks + Workforce","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/quickbooksWorkforce.png","response_type":"platform","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"7190e177-3063-434e-8b8c-9e35d71d4f82","name":"Square + Team","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/squareTeam.svg","response_type":"platform","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"1fb913f4-40c9-4914-a3c5-0c334b6e8fbe","name":"Greenshades","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/greenshades.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"a05347cd-fed3-4169-8f44-f71c9128e30b","name":"Heartland","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/heartland.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"aad0faef-d1f3-444b-89b8-a7e54876dd6f","name":"BambooHr","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/bambooHr.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false}]}}' diff --git a/app/spec/req_cache/get_sandbox.getpinwheel.com_64c73dd858d0311e9b255f16bf8d19d65dcc8199.yml b/app/spec/req_cache/get_sandbox.getpinwheel.com_64c73dd858d0311e9b255f16bf8d19d65dcc8199.yml new file mode 100644 index 000000000..8e4545ebb --- /dev/null +++ b/app/spec/req_cache/get_sandbox.getpinwheel.com_64c73dd858d0311e9b255f16bf8d19d65dcc8199.yml @@ -0,0 +1,31 @@ +--- +:scope: +:url: https://sandbox.getpinwheel.com/v1/ui/search?&enable_fuzzy_search=true +:body: '' +:status: 200 +:method: get +:headers: + Date: Tue, 08 Apr 2025 21:46:56 GMT + Content-Type: application/json + Content-Length: '9687' + Connection: close + server: uvicorn + access-control-allow-origin: "*" + content-security-policy: frame-ancestors 'none' + strict-transport-security: max-age=31536000; includeSubDomains; + x-pinwheel-request-id: 37992ed6-9119-4dfc-9b8e-164cb750a125 +:content: '{"data":[{"id":"d66e65b2-536d-4b2d-b73c-f6addd66c0f4","name":"Amazon","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Amazon.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"453223da-2006-4f59-843a-15ca597f372e","name":"AT&T","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/AT%26T.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"d4568c30-a4ae-4b83-a691-c612b200d5b1","name":"Best + Buy","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Best%20Buy.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"90c532eb-ddde-4f1c-8379-7d2a4d8d90e7","name":"Chipotle","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Chipotle.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0ba48840-899b-4e23-9429-9456094bf1f1","name":"Circle + K","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Circle%20K.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"60de4e93-2832-45b9-8b9d-f98c627aa2ee","name":"Costco","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Costco.png","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"b928719f-533c-4fcf-bbc5-e62d6defa61a","name":"CVS + Health","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/CVS%20Health.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"dd65fb10-88c3-47c0-9eee-fbb17bb4f1cb","name":"Dollar + General","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Dollar%20General.png","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"776d4fdc-79ae-49ab-b337-77a54c0e2ca5","name":"Dollar + Tree / Family Dollar","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Dollar%20Tree.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"737d833a-1b68-44f7-92ae-3808374cb459","name":"DoorDash + (Dasher)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/DoorDash%20%28Dasher%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"d02a6913-f0b3-4cf3-acfa-a05fa0646261","name":"GrubHub + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/GrubHub%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"6d0de266-c30d-4755-a589-600a604037ae","name":"HCA + Healthcare","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/HCA%20Healthcare.png","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"0e22141d-9ad8-46ee-94d3-ab77b95aceba","name":"Home + Depot","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Home%20Depot.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"b7af52b7-e610-4a97-9342-dc39163ca2df","name":"Kroger","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Kroger.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"59595148-c2b4-4bc7-8b1e-9d0d36587b67","name":"Lowe''s","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Lowe%27s.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"70b2bed2-ada8-49ec-99c2-691cc7d28df6","name":"Lyft + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Lyft%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"220f3b99-d489-4376-ba1c-6cee39cc5fdc","name":"Publix","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Publix.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"5e55be4d-0393-4e64-928d-e24f2bea80fd","name":"Target","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Target.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"91063607-2b4a-4c8e-8045-a543f01b8b09","name":"Uber + (Driver)","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Uber%20%28Driver%29.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"165f617a-31d5-4cc4-9495-8304e049ba2f","name":"UPS","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/United%20Parcel%20Service.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"b160a45a-12f8-4cff-a038-4977c167c381","name":"USPS","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/United%20States%20Postal%20Service.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"6cac3ecd-cef3-4e03-bfe1-a04c28e58bdd","name":"Waffle + House","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Waffle%20House.svg","response_type":"employer","amount_supported":false,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"1d6207d3-7bf0-4a1c-99f5-82af61572775","name":"Walmart","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/employers/logos/Walmart.svg","response_type":"employer","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":false,"default_guided_switch":false},{"id":"5becff90-1e35-450a-8995-13ac411e749b","name":"ADP","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/adpPortal.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"3f812c04-ac83-495b-99ca-7ec7d56dc68b","name":"Paycom","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paycom.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"9a4e213b-aeed-4cb2-aace-696bcd2b1e0d","name":"Paychex + Flex","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paychex.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"913170d1-393c-4f35-8c23-df3133ce7529","name":"Paylocity","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paylocity.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"b0b655f8-4ae6-4d09-a60f-1df9a2a1fd16","name":"Paycor","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/paycor.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"0c271780-fd19-43e0-a721-89228bb5fc5e","name":"Ceridian + Dayforce","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/ceridian.png","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false},{"id":"4475fef1-018d-43b8-92cb-bd548f8fd278","name":"Gusto","platform_type":"payroll","logo_url":"https://cdn.getpinwheel.com/assets/platforms/logos/search/gusto.svg","response_type":"platform","amount_supported":true,"min_percentage":1,"max_percentage":99,"percentage_supported":true,"default_guided_switch":false}]}' diff --git a/app/spec/req_cache/options_api.getpinwheel.com_02620475cc6b3ccb5b80ab06426229fdbfcba952.yml b/app/spec/req_cache/options_api.getpinwheel.com_02620475cc6b3ccb5b80ab06426229fdbfcba952.yml new file mode 100644 index 000000000..056f115a9 --- /dev/null +++ b/app/spec/req_cache/options_api.getpinwheel.com_02620475cc6b3ccb5b80ab06426229fdbfcba952.yml @@ -0,0 +1,21 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744148823325 +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:47:03 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: TI-84 + vary: Origin + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-credentials: 'true' + access-control-allow-origin: https://cdn.getpinwheel.com + access-control-allow-headers: content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version + x-pinwheel-request-id: d5b128de-1d45-4360-8369-23166c81251e + strict-transport-security: max-age=31536000; includeSubDomains; +:content: OK diff --git a/app/spec/req_cache/options_api.getpinwheel.com_60faddcff6f8cec964bb23f295aecc3e7415a8d8.yml b/app/spec/req_cache/options_api.getpinwheel.com_60faddcff6f8cec964bb23f295aecc3e7415a8d8.yml new file mode 100644 index 000000000..f6d7a9fd5 --- /dev/null +++ b/app/spec/req_cache/options_api.getpinwheel.com_60faddcff6f8cec964bb23f295aecc3e7415a8d8.yml @@ -0,0 +1,21 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744148819510 +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:46:59 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: TI-84 + vary: Origin + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-credentials: 'true' + access-control-allow-origin: https://cdn.getpinwheel.com + access-control-allow-headers: content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version + x-pinwheel-request-id: b37ea7b7-fa81-4d97-be6e-bf4e3cd7ee14 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: OK diff --git a/app/spec/req_cache/options_api.getpinwheel.com_9f2d3c63d14cf18a6c45b7718c03ae34349fe5a9.yml b/app/spec/req_cache/options_api.getpinwheel.com_9f2d3c63d14cf18a6c45b7718c03ae34349fe5a9.yml new file mode 100644 index 000000000..79a9f5bc1 --- /dev/null +++ b/app/spec/req_cache/options_api.getpinwheel.com_9f2d3c63d14cf18a6c45b7718c03ae34349fe5a9.yml @@ -0,0 +1,21 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/step_result/?date=1744148821056 +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:47:01 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: TI-84 + vary: Origin + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-credentials: 'true' + access-control-allow-origin: https://cdn.getpinwheel.com + access-control-allow-headers: content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version + x-pinwheel-request-id: 4e2dd012-1763-40f5-9877-5b8ad76c9547 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: OK diff --git a/app/spec/req_cache/options_api.getpinwheel.com_a6e32a1af1dd5df5acb39bd183f80e661bfe5075.yml b/app/spec/req_cache/options_api.getpinwheel.com_a6e32a1af1dd5df5acb39bd183f80e661bfe5075.yml new file mode 100644 index 000000000..a88fc8c29 --- /dev/null +++ b/app/spec/req_cache/options_api.getpinwheel.com_a6e32a1af1dd5df5acb39bd183f80e661bfe5075.yml @@ -0,0 +1,21 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/initialize/ +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:46:56 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: TI-84 + vary: Origin + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-credentials: 'true' + access-control-allow-origin: https://cdn.getpinwheel.com + access-control-allow-headers: content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version + x-pinwheel-request-id: 84a8b13e-b093-4483-bbe0-6d7db4cbc4a5 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: OK diff --git a/app/spec/req_cache/options_api.getpinwheel.com_d45185aa271b3ae26515fbd0127e92685742ded0.yml b/app/spec/req_cache/options_api.getpinwheel.com_d45185aa271b3ae26515fbd0127e92685742ded0.yml new file mode 100644 index 000000000..df93185ef --- /dev/null +++ b/app/spec/req_cache/options_api.getpinwheel.com_d45185aa271b3ae26515fbd0127e92685742ded0.yml @@ -0,0 +1,21 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/initialization_context/?employer_id=5a8cfb92-3373-4e65-b41b-54e821e79671 +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:46:55 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: TI-84 + vary: Origin + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-credentials: 'true' + access-control-allow-origin: https://cdn.getpinwheel.com + access-control-allow-headers: content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version + x-pinwheel-request-id: 3378e0c3-aa0f-496c-9222-d51358537ecd + strict-transport-security: max-age=31536000; includeSubDomains; +:content: OK diff --git a/app/spec/req_cache/options_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6.yml b/app/spec/req_cache/options_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6.yml new file mode 100644 index 000000000..d9fc8d021 --- /dev/null +++ b/app/spec/req_cache/options_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6.yml @@ -0,0 +1,21 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/next/ +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:46:58 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: TI-84 + vary: Origin + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-credentials: 'true' + access-control-allow-origin: https://cdn.getpinwheel.com + access-control-allow-headers: content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version + x-pinwheel-request-id: 55916c68-e83a-4326-922c-989709b3e1a3 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: OK diff --git a/app/spec/req_cache/options_sandbox.getpinwheel.com_22882c5a8e22b9679ce42f01fe05bc0a7e0e72e7.yml b/app/spec/req_cache/options_sandbox.getpinwheel.com_22882c5a8e22b9679ce42f01fe05bc0a7e0e72e7.yml new file mode 100644 index 000000000..892d5be59 --- /dev/null +++ b/app/spec/req_cache/options_sandbox.getpinwheel.com_22882c5a8e22b9679ce42f01fe05bc0a7e0e72e7.yml @@ -0,0 +1,20 @@ +--- +:scope: +:url: https://sandbox.getpinwheel.com/v1/ui/initial_providers +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:46:55 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: uvicorn + access-control-allow-origin: "*" + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-headers: x-link-token + content-security-policy: frame-ancestors 'none' + strict-transport-security: max-age=31536000; includeSubDomains; + x-pinwheel-request-id: ad090900-68e6-49f4-bb77-bb424017fdc8 +:content: OK diff --git a/app/spec/req_cache/options_sandbox.getpinwheel.com_64c73dd858d0311e9b255f16bf8d19d65dcc8199.yml b/app/spec/req_cache/options_sandbox.getpinwheel.com_64c73dd858d0311e9b255f16bf8d19d65dcc8199.yml new file mode 100644 index 000000000..062a5cd37 --- /dev/null +++ b/app/spec/req_cache/options_sandbox.getpinwheel.com_64c73dd858d0311e9b255f16bf8d19d65dcc8199.yml @@ -0,0 +1,20 @@ +--- +:scope: +:url: https://sandbox.getpinwheel.com/v1/ui/search?&enable_fuzzy_search=true +:body: '' +:status: 200 +:method: options +:headers: + Date: Tue, 08 Apr 2025 21:46:55 GMT + Content-Type: text/plain; charset=utf-8 + Content-Length: '2' + Connection: close + server: uvicorn + access-control-allow-origin: "*" + access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT + access-control-max-age: '600' + access-control-allow-headers: x-link-token + content-security-policy: frame-ancestors 'none' + strict-transport-security: max-age=31536000; includeSubDomains; + x-pinwheel-request-id: ed1cfc7f-e1f4-4cff-9c7c-44f4467027e7 +:content: OK diff --git a/app/spec/req_cache/post_api.getpinwheel.com_a6e32a1af1dd5df5acb39bd183f80e661bfe5075_1e5c5006f1bdd570aa3c4760c94ac333037a8384.yml b/app/spec/req_cache/post_api.getpinwheel.com_a6e32a1af1dd5df5acb39bd183f80e661bfe5075_1e5c5006f1bdd570aa3c4760c94ac333037a8384.yml new file mode 100644 index 000000000..7f029587e --- /dev/null +++ b/app/spec/req_cache/post_api.getpinwheel.com_a6e32a1af1dd5df5acb39bd183f80e661bfe5075_1e5c5006f1bdd570aa3c4760c94ac333037a8384.yml @@ -0,0 +1,22 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/initialize/ +:body: '{"employer_id":"5a8cfb92-3373-4e65-b41b-54e821e79671","job":"login"}' +:status: 200 +:method: post +:headers: + Date: Tue, 08 Apr 2025 21:46:57 GMT + Content-Type: application/json + Content-Length: '696' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: 5147bb92-14a0-4efd-9b37-d2b115cee031 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"response_type":"next","template":{"template_type":"form","fields":[{"key":"company","field_type":"text","field_subtype":"plaintext","label":"Workday + Organization ID","locked_field":false,"min_length":null,"max_length":null,"pattern":"^\\S*$","placeholder":"ex. + chipotle, circlek, etc.","options":null,"payload":null,"hint":{"label":"What is + my Workday Organization ID?","text_list":["To find your employer''s Workday Organization + ID, log into your Workday account, click on Profile (button in top right), then + click on My Account, then click on Organization ID."]},"initial_value":null,"should_obfuscate":false}],"title":"","subtitle":"","text_list":[],"actions":[],"button_text":null}}}' diff --git a/app/spec/req_cache/post_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6_1d4fc715ab4ad763b9d563c541d1fd3481631408.yml b/app/spec/req_cache/post_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6_1d4fc715ab4ad763b9d563c541d1fd3481631408.yml new file mode 100644 index 000000000..338ad5f56 --- /dev/null +++ b/app/spec/req_cache/post_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6_1d4fc715ab4ad763b9d563c541d1fd3481631408.yml @@ -0,0 +1,17 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/next/ +:body: '{"encryption_info":null,"payload":{"username":"user_good","password":"pass_good"}}' +:status: 200 +:method: post +:headers: + Date: Tue, 08 Apr 2025 21:47:02 GMT + Content-Type: application/json + Content-Length: '68' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: 0dd50c9f-eb35-4b9d-b662-1502986117b2 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"response_type":"processing","title":null,"subtitle":null}}' diff --git a/app/spec/req_cache/post_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6_69691c1432e64414d6b8aefb8f95626ec33203f4.yml b/app/spec/req_cache/post_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6_69691c1432e64414d6b8aefb8f95626ec33203f4.yml new file mode 100644 index 000000000..1ba7a2a56 --- /dev/null +++ b/app/spec/req_cache/post_api.getpinwheel.com_f0d59ea3930a5cbf0d57ea14b987e85e4fed55f6_69691c1432e64414d6b8aefb8f95626ec33203f4.yml @@ -0,0 +1,17 @@ +--- +:scope: +:url: https://api.getpinwheel.com/v1/link/ui/next/ +:body: '{"encryption_info":null,"payload":{"company":"company_good"}}' +:status: 200 +:method: post +:headers: + Date: Tue, 08 Apr 2025 21:46:59 GMT + Content-Type: application/json + Content-Length: '68' + Connection: close + server: TI-84 + access-control-allow-origin: "*" + access-control-allow-credentials: 'true' + x-pinwheel-request-id: 7ab3fdf6-01e0-44b2-8943-4a66df24dde5 + strict-transport-security: max-age=31536000; includeSubDomains; +:content: '{"data":{"response_type":"processing","title":null,"subtitle":null}}' diff --git a/app/spec/support/e2e_test_helpers.rb b/app/spec/support/e2e_test_helpers.rb index a653cf1f8..064c7f264 100644 --- a/app/spec/support/e2e_test_helpers.rb +++ b/app/spec/support/e2e_test_helpers.rb @@ -1,3 +1,5 @@ +require 'billy/capybara/rspec' + module E2eTestHelpers def verify_page(page, title:, wait: Capybara.default_max_wait_time) expect(page).to have_content(title, wait: wait) @@ -12,4 +14,122 @@ def verify_page(page, title:, wait: Capybara.default_max_wait_time) ERROR end end + + HARDCODED_ACCOUNT_ID = "5a8cfb92-3373-4e65-b41b-54e821e79671" + HARDCODED_PLATFORM_ID = "5965580e-380f-4b86-8a8a-7278c77f73cb" + + def simulate_next_step_and_webhooks + Billy.proxy.stub(%r{ui/step_result}, method: "get").and_return(headers: { + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers' => 'Content-Type, Authorization' + }, + json: { + "data": { + "response_type": "success", + "account_id": HARDCODED_ACCOUNT_ID, + "masked_accounts": nil + } + } + ) + simulate_account_added_event(CbvFlow.last) + end + + def simulate_account_added_event(cbv_flow) + pinwheel = Aggregators::Sdk::PinwheelService.new("sandbox") + @payroll_account = cbv_flow.payroll_accounts.find_or_create_by(type: :pinwheel, pinwheel_account_id: HARDCODED_ACCOUNT_ID) do |new_payroll_account| + new_payroll_account.supported_jobs = pinwheel.fetch_platform(platform_id: HARDCODED_PLATFORM_ID)["data"]["supported_jobs"] + end + + + @webhook_event = WebhookEvent.create!( + payroll_account: @payroll_account, + event_name: "account.added", + event_outcome: "success", + ) + end + + def mock_cbv_flow_responses + headahs = { + 'Access-Control-Allow-Origin' => 'https://cdn.getpinwheel.com', + 'Access-Control-Allow-Credentials' => 'true', + "My-Awesome-Debug-Headah" => "IM WALKING HERE", + 'Access-Control-Allow-Methods' => 'DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT', + 'Access-Control-Allow-Headers' => 'content-type,dersh-id,login_attempt_id,modal_session_id,pinwheel-link-token,unique_user_id,x-ct,x-sdk,x-sdk-version' + } + Billy.proxy.stub(/step_result/, method: "options").and_return(headers: headahs, body: "OK", code: 200) + Billy.proxy.stub(/ui\/next/, method: "options").and_return(headers: headahs, body: "OK", code: 200) + Billy.proxy.stub(/step_result/).and_return(headers: { + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers' => 'Content-Type, Authorization' + }, + json: { + "data": { + "response_type": "next", + "template": { + "template_type": "form", + "fields": [ + { + "key": "username", + "field_type": "text", + "field_subtype": "plaintext", + "label": "Username", + "locked_field": false, + "min_length": nil, + "max_length": nil, + "pattern": nil, + "placeholder": nil, + "options": nil, + "payload": nil, + "hint": nil, + "initial_value": nil, + "should_obfuscate": false + }, + { + "key": "password", + "field_type": "text", + "field_subtype": "password", + "label": "Password", + "locked_field": false, + "min_length": nil, + "max_length": nil, + "pattern": nil, + "placeholder": nil, + "options": nil, + "payload": nil, + "hint": nil, + "initial_value": nil, + "should_obfuscate": true + } + ], + "title": "Log into your payroll account", + "subtitle": "Enter your login credentials to continue", + "text_list": [], + "actions": [], + "button_text": nil + } + } + } + + + + + + + ) + Billy.proxy.stub(%r{ui/next}, method: "post").and_return(headers: { + 'Access-Control-Allow-Origin' => '*', + 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers' => 'Content-Type, Authorization' + }, + json: { + "data": { + "response_type": "processing", + "title": nil, + "subtitle": nil + } + } + ) + end end