Repository: SpartnerNL/Laravel-Excel
Branch: 3.1
Commit: 1854739267d8
Files: 311
Total size: 755.5 KB
Directory structure:
gitextract_hvn1oki5/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 1_Bug_report.yml
│ │ └── config.yml
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── SUPPORT.md
│ ├── issuecomplete.yml
│ ├── stale.yml
│ └── workflows/
│ └── run-tests.yml
├── .gitignore
├── .phpunit.cache/
│ └── test-results
├── .styleci.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── composer.json
├── config/
│ └── excel.php
├── phpunit.xml.dist
├── src/
│ ├── Cache/
│ │ ├── BatchCache.php
│ │ ├── BatchCacheDeprecated.php
│ │ ├── CacheManager.php
│ │ ├── MemoryCache.php
│ │ └── MemoryCacheDeprecated.php
│ ├── Cell.php
│ ├── ChunkReader.php
│ ├── Concerns/
│ │ ├── Exportable.php
│ │ ├── FromArray.php
│ │ ├── FromCollection.php
│ │ ├── FromGenerator.php
│ │ ├── FromIterator.php
│ │ ├── FromQuery.php
│ │ ├── FromView.php
│ │ ├── HasReferencesToOtherSheets.php
│ │ ├── Importable.php
│ │ ├── MapsCsvSettings.php
│ │ ├── OnEachRow.php
│ │ ├── PersistRelations.php
│ │ ├── RegistersEventListeners.php
│ │ ├── RemembersChunkOffset.php
│ │ ├── RemembersRowNumber.php
│ │ ├── ShouldAutoSize.php
│ │ ├── ShouldQueueWithoutChain.php
│ │ ├── SkipsEmptyRows.php
│ │ ├── SkipsErrors.php
│ │ ├── SkipsFailures.php
│ │ ├── SkipsOnError.php
│ │ ├── SkipsOnFailure.php
│ │ ├── SkipsUnknownSheets.php
│ │ ├── ToArray.php
│ │ ├── ToCollection.php
│ │ ├── ToModel.php
│ │ ├── WithBackgroundColor.php
│ │ ├── WithBatchInserts.php
│ │ ├── WithCalculatedFormulas.php
│ │ ├── WithCharts.php
│ │ ├── WithChunkReading.php
│ │ ├── WithColumnFormatting.php
│ │ ├── WithColumnLimit.php
│ │ ├── WithColumnWidths.php
│ │ ├── WithConditionalSheets.php
│ │ ├── WithCustomChunkSize.php
│ │ ├── WithCustomCsvSettings.php
│ │ ├── WithCustomQuerySize.php
│ │ ├── WithCustomStartCell.php
│ │ ├── WithCustomValueBinder.php
│ │ ├── WithDefaultStyles.php
│ │ ├── WithDrawings.php
│ │ ├── WithEvents.php
│ │ ├── WithFormatData.php
│ │ ├── WithGroupedHeadingRow.php
│ │ ├── WithHeadingRow.php
│ │ ├── WithHeadings.php
│ │ ├── WithLimit.php
│ │ ├── WithMappedCells.php
│ │ ├── WithMapping.php
│ │ ├── WithMultipleSheets.php
│ │ ├── WithPreCalculateFormulas.php
│ │ ├── WithProgressBar.php
│ │ ├── WithProperties.php
│ │ ├── WithReadFilter.php
│ │ ├── WithSkipDuplicates.php
│ │ ├── WithStartRow.php
│ │ ├── WithStrictNullComparison.php
│ │ ├── WithStyles.php
│ │ ├── WithTitle.php
│ │ ├── WithUpsertColumns.php
│ │ ├── WithUpserts.php
│ │ └── WithValidation.php
│ ├── Console/
│ │ ├── ExportMakeCommand.php
│ │ ├── ImportMakeCommand.php
│ │ ├── WithModelStub.php
│ │ └── stubs/
│ │ ├── export.model.stub
│ │ ├── export.plain.stub
│ │ ├── export.query-model.stub
│ │ ├── export.query.stub
│ │ ├── import.collection.stub
│ │ └── import.model.stub
│ ├── DefaultValueBinder.php
│ ├── DelegatedMacroable.php
│ ├── Events/
│ │ ├── AfterBatch.php
│ │ ├── AfterChunk.php
│ │ ├── AfterImport.php
│ │ ├── AfterSheet.php
│ │ ├── BeforeExport.php
│ │ ├── BeforeImport.php
│ │ ├── BeforeSheet.php
│ │ ├── BeforeWriting.php
│ │ ├── Event.php
│ │ └── ImportFailed.php
│ ├── Excel.php
│ ├── ExcelServiceProvider.php
│ ├── Exceptions/
│ │ ├── ConcernConflictException.php
│ │ ├── LaravelExcelException.php
│ │ ├── NoFilePathGivenException.php
│ │ ├── NoFilenameGivenException.php
│ │ ├── NoSheetsFoundException.php
│ │ ├── NoTypeDetectedException.php
│ │ ├── RowSkippedException.php
│ │ ├── SheetNotFoundException.php
│ │ └── UnreadableFileException.php
│ ├── Exporter.php
│ ├── Facades/
│ │ └── Excel.php
│ ├── Factories/
│ │ ├── ReaderFactory.php
│ │ └── WriterFactory.php
│ ├── Fakes/
│ │ ├── ExcelFake.php
│ │ └── fake_file
│ ├── Files/
│ │ ├── Disk.php
│ │ ├── Filesystem.php
│ │ ├── LocalTemporaryFile.php
│ │ ├── RemoteTemporaryFile.php
│ │ ├── TemporaryFile.php
│ │ └── TemporaryFileFactory.php
│ ├── Filters/
│ │ ├── ChunkReadFilter.php
│ │ └── LimitFilter.php
│ ├── HasEventBus.php
│ ├── HeadingRowImport.php
│ ├── Helpers/
│ │ ├── ArrayHelper.php
│ │ ├── CellHelper.php
│ │ └── FileTypeDetector.php
│ ├── Importer.php
│ ├── Imports/
│ │ ├── EndRowFinder.php
│ │ ├── HeadingRowExtractor.php
│ │ ├── HeadingRowFormatter.php
│ │ ├── ModelImporter.php
│ │ ├── ModelManager.php
│ │ └── Persistence/
│ │ └── CascadePersistManager.php
│ ├── Jobs/
│ │ ├── AfterImportJob.php
│ │ ├── AppendDataToSheet.php
│ │ ├── AppendPaginatedToSheet.php
│ │ ├── AppendQueryToSheet.php
│ │ ├── AppendViewToSheet.php
│ │ ├── CloseSheet.php
│ │ ├── ExtendedQueueable.php
│ │ ├── Middleware/
│ │ │ └── LocalizeJob.php
│ │ ├── ProxyFailures.php
│ │ ├── QueueExport.php
│ │ ├── QueueImport.php
│ │ ├── ReadChunk.php
│ │ └── StoreQueuedExport.php
│ ├── MappedReader.php
│ ├── Middleware/
│ │ ├── CellMiddleware.php
│ │ ├── ConvertEmptyCellValuesToNull.php
│ │ └── TrimCellValue.php
│ ├── Mixins/
│ │ ├── DownloadCollectionMixin.php
│ │ ├── DownloadQueryMacro.php
│ │ ├── ImportAsMacro.php
│ │ ├── ImportMacro.php
│ │ ├── StoreCollectionMixin.php
│ │ └── StoreQueryMacro.php
│ ├── QueuedWriter.php
│ ├── Reader.php
│ ├── RegistersCustomConcerns.php
│ ├── Row.php
│ ├── SettingsProvider.php
│ ├── Sheet.php
│ ├── Transactions/
│ │ ├── DbTransactionHandler.php
│ │ ├── NullTransactionHandler.php
│ │ ├── TransactionHandler.php
│ │ └── TransactionManager.php
│ ├── Validators/
│ │ ├── Failure.php
│ │ ├── RowValidator.php
│ │ └── ValidationException.php
│ └── Writer.php
└── tests/
├── Cache/
│ └── BatchCacheTest.php
├── CellTest.php
├── Concerns/
│ ├── ExportableTest.php
│ ├── FromArrayTest.php
│ ├── FromCollectionTest.php
│ ├── FromGeneratorTest.php
│ ├── FromIteratorTest.php
│ ├── FromQueryTest.php
│ ├── FromViewTest.php
│ ├── ImportableTest.php
│ ├── OnEachRowTest.php
│ ├── RegistersEventListenersTest.php
│ ├── RemembersChunkOffsetTest.php
│ ├── RemembersRowNumberTest.php
│ ├── ShouldQueueWithoutChainTest.php
│ ├── SkipsEmptyRowsTest.php
│ ├── SkipsOnErrorTest.php
│ ├── SkipsOnFailureTest.php
│ ├── ToArrayTest.php
│ ├── ToCollectionTest.php
│ ├── ToModelTest.php
│ ├── WithBackgroundColorTest.php
│ ├── WithBatchInsertsTest.php
│ ├── WithCalculatedFormulasTest.php
│ ├── WithChunkReadingTest.php
│ ├── WithColumnFormattingTest.php
│ ├── WithColumnLimitTest.php
│ ├── WithColumnWidthsTest.php
│ ├── WithConditionalSheetsTest.php
│ ├── WithCustomCsvSettingsTest.php
│ ├── WithCustomQuerySizeTest.php
│ ├── WithCustomStartCellTest.php
│ ├── WithCustomValueBinderTest.php
│ ├── WithDefaultStylesTest.php
│ ├── WithEventsTest.php
│ ├── WithFormatDataTest.php
│ ├── WithGroupedHeadingRowTest.php
│ ├── WithHeadingRowTest.php
│ ├── WithHeadingsTest.php
│ ├── WithLimitTest.php
│ ├── WithMappedCellsTest.php
│ ├── WithMappingTest.php
│ ├── WithMultipleSheetsTest.php
│ ├── WithPropertiesTest.php
│ ├── WithReadFilterTest.php
│ ├── WithSkipDuplicatesTest.php
│ ├── WithStartRowTest.php
│ ├── WithStrictNullComparisonTest.php
│ ├── WithStylesTest.php
│ ├── WithTitleTest.php
│ ├── WithUpsertsTest.php
│ └── WithValidationTest.php
├── Data/
│ ├── Disks/
│ │ └── .gitignore
│ └── Stubs/
│ ├── AfterQueueExportJob.php
│ ├── AfterQueueImportJob.php
│ ├── BeforeExportListener.php
│ ├── ChainedJobStub.php
│ ├── CustomConcern.php
│ ├── CustomSheetConcern.php
│ ├── CustomTransactionHandler.php
│ ├── Database/
│ │ ├── Factories/
│ │ │ ├── GroupFactory.php
│ │ │ └── UserFactory.php
│ │ ├── Group.php
│ │ ├── Migrations/
│ │ │ ├── 0000_00_00_000000_create_groups_table.php
│ │ │ ├── 0000_00_00_000001_create_group_user_table.php
│ │ │ ├── 0000_00_00_000002_add_group_id_to_users_table.php
│ │ │ └── 0000_00_00_000002_add_options_to_users.php
│ │ └── User.php
│ ├── EloquentCollectionWithMappingExport.php
│ ├── EloquentLazyCollectionExport.php
│ ├── EloquentLazyCollectionQueuedExport.php
│ ├── EmptyExport.php
│ ├── ExportWithEvents.php
│ ├── ExportWithEventsChunks.php
│ ├── ExportWithRegistersEventListeners.php
│ ├── FromGroupUsersQueuedQueryExport.php
│ ├── FromNestedArraysQueryExport.php
│ ├── FromNonEloquentQueryExport.php
│ ├── FromQueryWithCustomQuerySize.php
│ ├── FromUsersQueryExport.php
│ ├── FromUsersQueryExportWithEagerLoad.php
│ ├── FromUsersQueryExportWithMapping.php
│ ├── FromUsersQueryExportWithPrepareRows.php
│ ├── FromUsersQueryWithJoinExport.php
│ ├── FromUsersScoutExport.php
│ ├── FromViewExportWithMultipleSheets.php
│ ├── ImportWithEvents.php
│ ├── ImportWithEventsChunksAndBatches.php
│ ├── ImportWithRegistersEventListeners.php
│ ├── QueueImportWithoutJobChaining.php
│ ├── QueuedExport.php
│ ├── QueuedExportWithFailedEvents.php
│ ├── QueuedExportWithFailedHook.php
│ ├── QueuedExportWithLocalePreferences.php
│ ├── QueuedImport.php
│ ├── QueuedImportWithFailure.php
│ ├── QueuedImportWithMiddleware.php
│ ├── QueuedImportWithRetryUntil.php
│ ├── SheetForUsersFromView.php
│ ├── SheetWith100Rows.php
│ ├── ShouldQueueExport.php
│ ├── Views/
│ │ └── users.blade.php
│ ├── WithMappingExport.php
│ └── WithTitleExport.php
├── DelegatedMacroableTest.php
├── ExcelFakeTest.php
├── ExcelServiceProviderTest.php
├── ExcelTest.php
├── HeadingRowImportTest.php
├── Helpers/
│ └── FileHelper.php
├── InteractsWithQueueTest.php
├── Mixins/
│ ├── DownloadCollectionTest.php
│ ├── DownloadQueryMacroTest.php
│ ├── ImportAsMacroTest.php
│ ├── ImportMacroTest.php
│ ├── StoreCollectionTest.php
│ └── StoreQueryMacroTest.php
├── QueuedExportTest.php
├── QueuedImportTest.php
├── QueuedQueryExportTest.php
├── QueuedViewExportTest.php
├── TemporaryFileTest.php
├── TestCase.php
└── Validators/
└── RowValidatorTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
* text eol=lf
/.github export-ignore
/tests export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
phpunit.xml.dist export-ignore
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: patrickbrouwers
custom: https://laravel-excel.com/commercial-support
================================================
FILE: .github/ISSUE_TEMPLATE/1_Bug_report.yml
================================================
name: Bug Report
description: Report a general package issue. Filling in the issue template is mandatory, issues without it will be closed. Please ensure your Laravel-Excel version is still supported (Currently ^3.1)
title: "[Bug]: "
labels: [bug]
body:
- type: checkboxes
id: terms
attributes:
label: Is the bug applicable and reproducable to the latest version of the package and hasn't it been reported before?
description: Currently 3.1.x
options:
- label: Yes, it's still reproducable
required: true
- type: input
attributes:
label: What version of Laravel Excel are you using?
description: 'For example: 3.1.30'
validations:
required: true
- type: input
attributes:
label: What version of Laravel are you using?
description: 'For example: 7.1.10'
validations:
required: true
- type: input
attributes:
label: What version of PHP are you using?
description: 'For example: 8.1.0'
validations:
required: true
- type: textarea
attributes:
label: Describe your issue
description: Describe the problem you're seeing, Please be short, but concise.
validations:
required: true
- type: textarea
attributes:
label: How can the issue be reproduced?
description: Please provide easy-to-reproduce steps (repository, simple code example, failing unit test). Please don't paste your entire code, but create a reproducable scenario that can be tested using a simple User model in a blank Laravel installation.
validations:
required: true
- type: textarea
attributes:
label: What should be the expected behaviour?
description: Please describe what the expected outcome should be. Any suggestions to what is wrong?
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: 🧐 Questions
url: https://github.com/SpartnerSoftware/Laravel-Excel/discussions
about: The issuer tracker is focused on reporting bugs or problems. Please use the Discussions tabs for questions!
- name: 💡 Proposals
url: https://github.com/SpartnerSoftware/Laravel-Excel/discussions
about: If you have a 🔥 idea. Please use the Discussions tab for this!
- name: 📚 Documentation improvements
url: https://github.com/SpartnerSoftware/laravel-excel-docs
about: Our documentation is open-source, you can make a PR with your suggested changes over there.
- name: Commercial Support
url: https://laravel-excel.com/commercial-support
about: If you need urgent help we can offer this on commercial basis. Send us an e-mail to discuss the posibilities and our hourly rate.
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
1️⃣ Is the bug applicable and reproducable to the latest version of the package and hasn't it been reported before? (Currently 3.1.x)
2️⃣ What version of the package, Laravel and PHP do you use? Please provide the FULL version number.
- Laravel Excel version: [e.g. 3.1.30]
- Laravel version: [e.g. 8.3.1]
- PHP version: [e.g. 7.4.0]
3️⃣ Describe your issue. Please be short, but concise.
4️⃣ How can the issue be reproduced? Please provide easy-to-reproduce steps (repository, simple code example, failing unit test).
5️⃣ What should be the expected behaviour?
6️⃣ Have you filled in the entire issue template? If not, your issue will be closed. Thanks for using the package! 🙌
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
Please take note of our contributing guidelines: https://docs.laravel-excel.com/3.1/getting-started/contributing.html
Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.
1️⃣ Why should it be added? What are the benefits of this change?
2️⃣ Does it contain multiple, unrelated changes? Please separate the PRs out.
3️⃣ Does it include tests, if possible?
4️⃣ Any drawbacks? Possible breaking changes?
5️⃣ Mark the following tasks as done:
- [ ] Checked the codebase to ensure that your feature doesn't already exist.
- [ ] Take note of the contributing guidelines.
- [ ] Checked the pull requests to ensure that another person hasn't already submitted a fix.
- [ ] Added tests to ensure against regression.
6️⃣ Thanks for contributing! 🙌
================================================
FILE: .github/SUPPORT.md
================================================
# Support
This repository is focused on bugs and issues. We unfortunately can't answer all support questions in a timely manner. Our software is free and open source, meaning that the use of our software is optional.
We hold no liability and there is no obligation to support. We will provide support on a best effort basis.
If you use the software commercially and need elaborate support or need it urgently, we can offer this on a commercial basis.
Please contact info@spartner.nl or via phone +31 (0)10 744 9312 or visit the dedicated page with more information:
https://laravel-excel.com/commercial-support
Also note that we are a wrapper package around PhpSpreadsheet and thus we cannot answer all questions that are about PhpSpreadsheet functionality. You could ask your question on Stackoverflow or a Laravel-related forum:
- https://stackoverflow.com/questions/tagged/laravel-excel
- https://laracasts.com/discuss
- https://laravel.io/forum
More information about support you can find in the documentation: https://docs.laravel-excel.com/3.1/getting-started/support.html
Thanks!
================================================
FILE: .github/issuecomplete.yml
================================================
# The name of the label to apply when an issue does not have all tasks checked
labelName: more information needed
# The text of the comment to add to the issue in addition to the label
commentText: >
Thanks for submitting the ticket. Unfortunately the information you provided is incomplete. We need to know which version you use and how to reproduce it. Please include code examples. Before we can pick it up, please check (https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/.github/ISSUE_TEMPLATE.md) and add the missing information.
To make processing of this ticket a lot easier, please make sure to check (https://laravel-excel.maatwebsite.nl/3.1/getting-started/contributing.html) and double-check if you have filled in the issue template correctly. This will allow us to pick up your ticket more efficiently. Issues that don't have an issue template filled in, will be closed.
# Whether or not to ensure all checkboxes are checked
checkCheckboxes: false
# Keywords to look for in the body of the issue
keywords:
- Versions
- Description
================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 1
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- proposal
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: false
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This bug report has been automatically closed because it has not had
recent activity. If this is still an active bug, please comment to reopen.
Thank you for your contributions.
================================================
FILE: .github/workflows/run-tests.yml
================================================
name: Run tests
on:
push:
pull_request:
schedule:
- cron: '0 0 * * *'
jobs:
tests:
if: "!contains(github.event.head_commit.message, 'skip ci')"
runs-on: ${{ matrix.os }}
services:
mysql:
image: mysql:5.7
env:
MYSQL_DATABASE: laravel_excel
MYSQL_ALLOW_EMPTY_PASSWORD: yes
ports:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
matrix:
php: [7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5]
laravel: [13, 12, 11, 10, 9, 8, 7, 6, 5.8]
dependency-version: [prefer-stable]
os: [ubuntu-latest]
include:
- laravel: 13
scout: 11.*
testbench: 11.*
- laravel: 12
scout: 10.*
testbench: 10.*
- laravel: 11
scout: 10.*
testbench: 9.*
- laravel: 10
scout: 10.*
testbench: 8.*
- laravel: 9
scout: 9.*
testbench: 7.*
- laravel: 8
scout: 8.*
testbench: 6.*
- laravel: 7
scout: 7.2.*
testbench: 5.*
- laravel: 6
scout: 7.1.*
testbench: 4.*
- laravel: 5.8
scout: 7.1.*
testbench: 3.8.*
exclude:
- laravel: 13
php: 8.2
- laravel: 13
php: 8.1
- laravel: 13
php: 8.0
- laravel: 13
php: 7.4
- laravel: 12
php: 8.1
- laravel: 12
php: 8.0
- laravel: 12
php: 7.4
- laravel: 11
php: 8.5
- laravel: 11
php: 8.1
- laravel: 11
php: 8.0
- laravel: 11
php: 7.4
- laravel: 10
php: 8.0
- laravel: 10
php: 7.4
- laravel: 10
php: 8.4
- laravel: 10
php: 8.5
- laravel: 9
php: 7.4
- laravel: 9
php: 8.4
- laravel: 9
php: 8.5
- laravel: 8
php: 8.4
- laravel: 8
php: 8.5
- laravel: 7
php: 8.0
- laravel: 7
php: 8.1
- laravel: 7
php: 8.2
- laravel: 7
php: 8.3
- laravel: 7
php: 8.4
- laravel: 7
php: 8.5
- laravel: 6
php: 8.0
- laravel: 6
php: 8.1
- laravel: 6
php: 8.2
- laravel: 6
php: 8.3
- laravel: 6
php: 8.4
- laravel: 6
php: 8.5
- laravel: 5.8
php: 8.0
- laravel: 5.8
php: 8.1
- laravel: 5.8
php: 8.2
- laravel: 5.8
php: 8.3
- laravel: 5.8
php: 8.4
- laravel: 5.8
php: 8.5
name: PHP${{ matrix.php }} - L${{ matrix.laravel }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.composer/cache/files
key: dependency-cache-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, mysql, pdo_mysql, bcmath, intl, gd, exif, iconv
coverage: none
- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}.*" "orchestra/testbench:${{ matrix.testbench }}" "laravel/scout:${{ matrix.scout }}" --no-interaction --no-update
composer update --${{ matrix.dependency-version }} --no-interaction
- name: Install legacy factories
run: |
composer require "laravel/legacy-factories" -W --no-interaction
if: "matrix.laravel >= 8"
- name: Execute tests
run: vendor/bin/phpunit --testdox --configuration phpunit.xml.dist
env:
DB_PORT: ${{ job.services.mysql.ports[3306] }}
================================================
FILE: .gitignore
================================================
/vendor
composer.phar
composer.lock
.DS_Store
.idea
phpunit.xml
.phpunit.result.cache
================================================
FILE: .phpunit.cache/test-results
================================================
{"version":1,"defects":{"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_an_import_with_batch_cache":5,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_an_export_with_batch_cache":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_relation_query_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_eager_loads":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_eager_loads_and_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_without_using_eloquent":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_without_using_eloquent_and_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_with_nested_arrays":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_with_nested_arrays_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_batch_caching":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_prepare_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_scout":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::can_export_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::can_export_multiple_sheets_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file_from_uploaded_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_csv_file_with_html_tags_inside":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false":8,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::can_import_each_row_individually":8,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::it_respects_the_end_column":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::events_get_called_when_importing":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersChunkOffsetTest::can_access_chunk_offset_on_import_to_array_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_access_row_number_on_import_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts":8,"ShouldQueueWithoutChainTest::can_import_to_model_in_chunks":8,"ShouldQueueWithoutChainTest::can_import_to_model_without_job_chaining":8,"ShouldQueueWithoutChainTest::a_queue_name_can_be_specified_when_importing":8,"ShouldQueueWithoutChainTest::the_cleanup_only_runs_when_all_jobs_are_done":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_on_each_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::custom_skips_rows_when_using_oneachrow":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::can_skip_on_error":7,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::can_skip_errors_and_collect_all_errors_at_the_end":7,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_skip_on_error":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::skips_only_failed_rows_in_batch":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_skip_failures_and_collect_all_failures_at_the_end":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_validate_using_oneachrow_and_skipsonfailure":7,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_validate_using_tocollection_and_skipsonfailure":7,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::can_import_to_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::can_import_multiple_sheets_to_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::can_import_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::can_import_multiple_sheets_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_each_row_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::has_timestamps_when_imported_single_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_multiple_models_in_single_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_multiple_different_types_of_models_in_single_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::can_import_to_model_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::can_import_to_model_in_batches_bigger_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::can_import_multiple_different_types_of_models_in_single_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::has_timestamps_when_imported_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::by_default_does_not_calculate_formulas":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_multi_sheet_references":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_skips_empty":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas_and_skips_empty":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_un":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_csv_in_chunks_and_insert_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_array_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_catch_job_failed_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_array_and_format_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_array_in_chunks_without_formatting":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::can_import_to_array_with_column_limit":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::can_import_to_array_with_column_limit_and_skips_empty_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithConditionalSheetsTest::can_select_which_sheets_will_be_imported":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_read_csv_import_with_custom_settings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::cannot_read_with_wrong_delimiter":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomQuerySizeTest::can_export_with_custom_count":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::can_set_a_value_binder_on_import":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::import_events_get_called":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::import_chunked_events_get_called":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::by_default_import_to_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_array_with_format_data":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_array_with_format_data_and_skips_empty_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::by_default_import_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_collection_with_format_data":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::by_default_import_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_model_with_format_data":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_to_array_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_oneachrow_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_to_collection_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_each_row_to_model_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_each_row_to_model_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_each_row_to_model_with_different_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_to_array_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_empty_rows_with_header":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_empty_models_with_header":7,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_cast_empty_headers_to_indexed_int":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::can_import_a_limited_section_of_rows_to_model_with_different_start_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::can_import_to_array_with_limit":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::can_set_limit_bigger_than_row_size":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::can_import_with_references_to_cells":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::can_import_with_nested_references_to_cells":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::can_import_with_references_to_cells_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_export_with_multiple_sheets_using_collections":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_export_multiple_sheets_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_index_will_throw_sheet_not_found_exception":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_name_will_throw_sheet_not_found_exception":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_name_can_be_ignored":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_sheet":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_index_and_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name_and_index":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::can_import_each_row_to_model_with_different_start_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::can_import_to_array_with_start_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_batches_with_defined_upsert_columns":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_rows_with_defined_upsert_columns":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_closure_validation_rules":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_custom_validation_rule_objects":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_conditionality":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_unless_conditionality":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_combined_rules_with_colons":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_with_custom_attributes":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_with_custom_message":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_headings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_grouped_headings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_using_oneachrow":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_using_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_using_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_configure_validator":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_toarray":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_tocollection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_tomodel":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_oneachrow":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_skipsemptyrows":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_tsv_file":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_chain_imports":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_from_uploaded_file":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_from_real_path":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_without_extension_with_explicit_reader_type":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_model_collection_with_headings_as_excel":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::cannot_queue_import_that_does_not_implement_should_queue":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_an_import":7,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_an_import_with_batch_cache_and_file_store":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_import_with_remote_temp_disk":7,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_keep_extension_for_temp_file_on_remote_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_import_with_remote_temp_disk_and_prefix":7,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_automatically_delete_temp_file_on_failure_when_using_remote_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::cannot_automatically_delete_temp_file_on_failure_when_using_local_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_force_remote_download_and_deletion_for_each_chunk_on_queue":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_define_middleware_method_on_queued_import":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_define_retry_until_method_on_queued_import":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_define_max_exceptions_property_on_queued_import":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache_and_file_store":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export_with_mapping":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_scout_export":8,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::can_queue_an_export":8,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::can_export_multiple_sheets_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_from_lazy_collection":8,"Maatwebsite\\Excel\\Tests\\CellTest::can_get_cell_value":7,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::export_chunked_events_get_called":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromArrayTest::can_export_from_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_from_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_with_multiple_sheets_from_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_from_lazy_collection_with_queue":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnFormattingTest::can_export_with_column_formatting":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnWidthsTest::can_set_column_width":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_settings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_encoding":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomStartCellTest::can_store_collection_with_custom_start_cell":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::can_set_a_value_binder_on_export":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithDefaultStylesTest::can_configure_default_styles":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::can_export_from_collection_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::can_export_from_collection_with_multiple_heading_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::can_export_from_collection_with_heading_row_with_custom_start_cell":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::can_export_with_heading":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::can_return_multiple_rows_in_map":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::json_array_columns_shouldnt_be_detected_as_multiple_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exports_trailing_empty_cells":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exports_trailing_empty_cells_by_setting_config_strict_null_comparison":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStylesTest::can_configure_styles":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_store_csv_export_with_custom_settings":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_a_collection_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_a_collection_with_headers_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_collection_with_headers_with_hidden_eloquent_attributes":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_collection_with_headers_when_making_attributes_visible":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_set_custom_response_headers":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::can_download_a_query_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::can_download_a_collection_with_headers_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportAsMacroTest::can_import_directly_into_a_model_with_mapping":8,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportMacroTest::can_import_directly_into_a_model":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_collection_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_collection_as_excel_on_non_default_disk":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_collection_with_headings_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::can_download_a_query_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::can_download_a_query_as_excel_on_different_disk":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::can_store_a_query_with_headers_as_excel":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_an_export":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_an_export_and_store_on_different_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_with_remote_temp_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_with_remote_temp_disk_and_prefix":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_implicitly_queue_an_export":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_with_mapping_on_eloquent_models":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_set_locale_on_queue_export_job":8,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_not_flushing_the_cache":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_models_with_belongs_to_relations":7,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_models_with_belongs_to_many_relations":7,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_writes_to_cache_with_a_dateinterval_ttl":7,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter_with_key":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_with_custom_row_number":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_key":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_custom_row_number":5,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_heading_row_with_custom_formatter_defined_in_config":5,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_cannot_import_a_non_existing_xlsx_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_relation_query_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_eager_loads":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_eager_loads_and_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent_and_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays_queued":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_batch_caching":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_prepare_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_scout":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::test_can_export_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::test_can_export_multiple_sheets_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file_from_uploaded_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_csv_file_with_html_tags_inside":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false":8,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::test_can_import_each_row_individually":8,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::test_it_respects_the_end_column":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::test_events_get_called_when_importing":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersChunkOffsetTest::test_can_access_chunk_offset_on_import_to_array_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts":8,"ShouldQueueWithoutChainTest::test_can_import_to_model_in_chunks":8,"ShouldQueueWithoutChainTest::test_can_import_to_model_without_job_chaining":8,"ShouldQueueWithoutChainTest::test_a_queue_name_can_be_specified_when_importing":8,"ShouldQueueWithoutChainTest::test_the_cleanup_only_runs_when_all_jobs_are_done":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_on_each_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_custom_skips_rows_when_using_oneachrow":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::test_can_skip_on_error":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::test_can_skip_errors_and_collect_all_errors_at_the_end":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_skip_on_error":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_skips_only_failed_rows_in_batch":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_skip_failures_and_collect_all_failures_at_the_end":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_validate_using_oneachrow_and_skipsonfailure":8,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_validate_using_tocollection_and_skipsonfailure":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::test_can_import_to_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::test_can_import_multiple_sheets_to_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::test_can_import_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::test_can_import_multiple_sheets_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_each_row_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_has_timestamps_when_imported_single_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_multiple_models_in_single_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_multiple_different_types_of_models_in_single_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_models_with_belongs_to_relations":8,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_models_with_belongs_to_many_relations":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_can_import_to_model_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_can_import_to_model_in_batches_bigger_file":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_can_import_multiple_different_types_of_models_in_single_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_has_timestamps_when_imported_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_by_default_does_not_calculate_formulas":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_multi_sheet_references":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_skips_empty":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas_and_skips_empty":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_un":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_csv_in_chunks_and_insert_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_array_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_catch_job_failed_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_array_and_format_in_chunks":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_array_in_chunks_without_formatting":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::test_can_import_to_array_with_column_limit":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::test_can_import_to_array_with_column_limit_and_skips_empty_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithConditionalSheetsTest::test_can_select_which_sheets_will_be_imported":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_can_read_csv_import_with_custom_settings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_cannot_read_with_wrong_delimiter":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomQuerySizeTest::test_can_export_with_custom_count":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::test_can_set_a_value_binder_on_import":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_import_events_get_called":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_import_chunked_events_get_called":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_export_chunked_events_get_called":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_by_default_import_to_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_array_with_format_data":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_array_with_format_data_and_skips_empty_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_by_default_import_to_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_collection_with_format_data":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_by_default_import_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_model_with_format_data":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_to_array_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_oneachrow_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_to_collection_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_each_row_to_model_with_grouped_headers":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_each_row_to_model_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_each_row_to_model_with_different_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_to_array_with_heading_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_empty_rows_with_header":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_empty_models_with_header":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_cast_empty_headers_to_indexed_int":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::test_can_import_a_limited_section_of_rows_to_model_with_different_start_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::test_can_import_to_array_with_limit":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::test_can_set_limit_bigger_than_row_size":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::test_can_import_with_references_to_cells":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::test_can_import_with_nested_references_to_cells":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::test_can_import_with_references_to_cells_to_model":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_export_with_multiple_sheets_using_collections":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_export_multiple_sheets_from_view":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_index_will_throw_sheet_not_found_exception":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_name_will_throw_sheet_not_found_exception":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_name_can_be_ignored":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_sheet":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_index_and_name":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name_and_index":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::test_can_import_each_row_to_model_with_different_start_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::test_can_import_to_array_with_start_row":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_batches_with_defined_upsert_columns":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_rows_with_defined_upsert_columns":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_closure_validation_rules":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_custom_validation_rule_objects":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_conditionality":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_unless_conditionality":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_combined_rules_with_colons":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_with_custom_attributes":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_with_custom_attributes_pointing_to_another_attribute":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_with_custom_message":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_headings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_grouped_headings":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_in_batches":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_using_oneachrow":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_using_collection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_using_array":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_configure_validator":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_toarray":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_tocollection":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_tomodel":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_oneachrow":8,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_skipsemptyrows":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_tsv_file":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_chain_imports":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_from_uploaded_file":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_from_real_path":8,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_without_extension_with_explicit_reader_type":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::test_can_download_a_query_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::test_can_download_a_collection_with_headers_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportAsMacroTest::test_can_import_directly_into_a_model_with_mapping":8,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportMacroTest::test_can_import_directly_into_a_model":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::test_can_store_a_model_collection_with_headings_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::test_can_download_a_query_as_excel":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::test_can_download_a_query_as_excel_on_different_disk":8,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::test_can_store_a_query_with_headers_as_excel":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_cannot_queue_import_that_does_not_implement_should_queue":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_an_import":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_an_import_with_batch_cache_and_file_store":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_keep_extension_for_temp_file_on_remote_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk_and_prefix":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_automatically_delete_temp_file_on_failure_when_using_remote_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_cannot_automatically_delete_temp_file_on_failure_when_using_local_disk":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_force_remote_download_and_deletion_for_each_chunk_on_queue":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_define_middleware_method_on_queued_import":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_define_retry_until_method_on_queued_import":8,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_define_max_exceptions_property_on_queued_import":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_an_export":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_an_export_with_batch_cache_and_file_store":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_an_export_with_mapping":8,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_scout_export":8,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::test_can_queue_an_export":8,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::test_can_export_multiple_sheets_from_view":8,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_string_input_matching_pattern":7,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_required_without_all":7,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_required_without":7},"times":{"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_an_import_with_batch_cache":2.346,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_an_export":0.241,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_an_export_with_batch_cache":0.067,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache":0.374,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::will_get_multiple_from_memory_if_cells_hold_in_memory":0.02,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::will_get_multiple_from_cache_if_cells_are_persisted":0.002,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::will_get_multiple_from_cache_and_persisted":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_persists_to_cache_when_memory_limit_reached_on_setting_a_value":0,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_persists_to_cache_when_memory_limit_reached_on_setting_multiple_values":0,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_writes_to_cache_with_default_ttl#null (forever)":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_writes_to_cache_with_default_ttl#int value":0,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_writes_to_cache_with_default_ttl#callable":0,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_writes_to_cache_with_a_dateinterval_ttl":0,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::it_can_override_default_ttl":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::needs_to_have_a_file_name_when_downloading":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::needs_to_have_a_file_name_when_storing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::needs_to_have_a_file_name_when_queuing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::responsable_needs_to_have_file_name_configured_inside_the_export":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::is_responsable":0.037,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_have_customized_header":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_set_custom_headers_in_export_class":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_get_raw_export_contents":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_have_customized_disk_options_when_storing":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_have_customized_disk_options_when_queueing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_set_disk_options_in_export_class_when_storing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_set_disk_options_in_export_class_when_queuing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_override_export_class_disk_options_when_calling_store":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_override_export_class_disk_options_when_calling_queue":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_have_empty_disk_options_when_storing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::can_have_empty_disk_options_when_queueing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\FromArrayTest::can_export_from_array":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_from_collection":0.036,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_with_multiple_sheets_from_collection":0.139,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_from_lazy_collection":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\FromGeneratorTest::can_export_from_generator":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\FromIteratorTest::can_export_from_iterator":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file_from_uploaded_file":0.008,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_csv_file_with_html_tags_inside":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::can_import_each_row_individually":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::it_respects_the_end_column":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::events_get_called_when_exporting":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::events_get_called_when_importing":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::can_have_invokable_class_as_listener":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersChunkOffsetTest::can_set_and_get_chunk_offset":0,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersChunkOffsetTest::can_access_chunk_offset_on_import_to_array_in_chunks":0.249,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_set_and_get_row_number":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_access_row_number_on_import_to_model":0.185,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks":3.444,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts":3.44,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_collection":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_on_each_row":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_model":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_model":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::custom_skips_rows_when_using_oneachrow":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::can_import_to_array":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::can_import_multiple_sheets_to_array":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::can_import_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::can_import_multiple_sheets_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBackgroundColorTest::can_configure_background_color_from_rgb_string":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBackgroundColorTest::can_configure_background_color_as_array":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBackgroundColorTest::can_configure_background_color_with_color_instance":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::by_default_does_not_calculate_formulas":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_multi_sheet_references":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_skips_empty":0.018,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas_and_skips_empty":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnFormattingTest::can_export_with_column_formatting":0.008,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnWidthsTest::can_set_column_width":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_settings":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_encoding":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_read_csv_with_auto_detecting_delimiter_semicolon":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_read_csv_with_auto_detecting_delimiter_comma":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::can_read_csv_import_with_custom_settings":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::cannot_read_with_wrong_delimiter":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomStartCellTest::can_store_collection_with_custom_start_cell":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::can_set_a_value_binder_on_export":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::can_set_a_value_binder_on_import":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithDefaultStylesTest::can_configure_default_styles":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::export_events_get_called":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::import_events_get_called":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::import_chunked_events_get_called":0.499,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::can_have_invokable_class_as_listener":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::can_have_global_event_listeners":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::can_have_custom_concern_handlers":0.012,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::can_have_custom_sheet_concern_handlers":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::by_default_import_to_array":0.008,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_array_with_format_data":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_array_with_format_data_and_skips_empty_rows":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::by_default_import_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_collection_with_format_data":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::by_default_import_to_model":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::can_import_to_model_with_format_data":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::can_export_from_collection_with_heading_row":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::can_export_from_collection_with_multiple_heading_rows":0.021,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::can_export_from_collection_with_heading_row_with_custom_start_cell":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::can_export_with_heading":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::can_return_multiple_rows_in_map":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::json_array_columns_shouldnt_be_detected_as_multiple_rows":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithPropertiesTest::can_set_custom_document_properties":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithPropertiesTest::it_merges_with_default_properties":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithPropertiesTest::it_ignores_empty_properties":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithReadFilterTest::can_register_custom_read_filter":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exports_trailing_empty_cells":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::exports_trailing_empty_cells_by_setting_config_strict_null_comparison":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStylesTest::can_configure_styles":0.009,"Maatwebsite\\Excel\\Tests\\Concerns\\WithTitleTest::can_export_with_title":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithTitleTest::can_export_sheet_title_when_longer_than_max_length":0.006,"Maatwebsite\\Excel\\Tests\\DelegatedMacroableTest::can_call_methods_from_delegate":0.004,"Maatwebsite\\Excel\\Tests\\DelegatedMacroableTest::can_use_writer_macros":0.004,"Maatwebsite\\Excel\\Tests\\DelegatedMacroableTest::can_use_sheet_macros":0.004,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_fake_an_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_downloaded_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_stored_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_regex_against_a_fake_stored_export_with_multiple_files":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_stored_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_queued_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_implicitly_queued_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_queued_export_with_chain":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_raw_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_import":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_import_with_uploaded_file":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_queued_import":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_implicitly_queued_import":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::can_assert_against_a_fake_queued_import_with_chain":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_queued_export":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::custom_transaction_handler_is_bound":0.001,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::is_bound":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::has_aliased":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::registers_console_commands":0.006,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::sets_php_spreadsheet_settings":0,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_download_an_export_object_with_facade":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_download_an_export_object":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_store_an_export_object_on_default_disk":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_store_an_export_object_on_another_disk":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_store_csv_export_with_default_settings":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_get_raw_export_contents":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_store_tsv_export_with_default_settings":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_store_csv_export_with_custom_settings":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::cannot_use_from_collection_and_from_view_on_same_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_to_array":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_to_collection":0.039,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_to_collection_without_import_object":0.031,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_tsv_file":0.005,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_chain_imports":0.006,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_from_uploaded_file":0.004,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_a_simple_xlsx_file_from_real_path":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::import_will_throw_error_when_no_reader_type_could_be_detected_when_no_extension":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::import_will_throw_error_when_no_reader_type_could_be_detected_with_unknown_extension":0.013,"Maatwebsite\\Excel\\Tests\\ExcelTest::can_import_without_extension_with_explicit_reader_type":0.004,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row":0.059,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter_with_key":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_with_custom_row_number":0.008,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_key":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_custom_row_number":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::can_import_heading_row_with_custom_formatter_defined_in_config":0.003,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::read_chunk_job_can_interact_with_queue":0.001,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::append_data_to_sheet_job_can_interact_with_queue":0,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::append_query_to_sheet_job_can_interact_with_queue":0,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::append_view_to_sheet_job_can_interact_with_queue":0,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_a_collection_as_excel":0.008,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_a_collection_with_headers_as_excel":0.009,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_collection_with_headers_with_hidden_eloquent_attributes":0.007,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_download_collection_with_headers_when_making_attributes_visible":0.007,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::can_set_custom_response_headers":0.005,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_collection_as_excel":0.011,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_collection_as_excel_on_non_default_disk":0.006,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_collection_with_headings_as_excel":0.007,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::can_store_a_model_collection_with_headings_as_excel":0.008,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_an_export_and_store_on_different_disk":0.234,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_with_remote_temp_disk":0.276,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_with_remote_temp_disk_and_prefix":0.24,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_implicitly_queue_an_export":0.241,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_with_mapping_on_eloquent_models":0.017,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_catch_failures":0.007,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_catch_failures_on_queue_export_job":0.003,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_set_locale_on_queue_export_job":0.015,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::can_queue_export_not_flushing_the_cache":0.294,"Maatwebsite\\Excel\\Tests\\TemporaryFileTest::can_use_default_rights":0.001,"Maatwebsite\\Excel\\Tests\\TemporaryFileTest::can_use_dir_rights":0.001,"Maatwebsite\\Excel\\Tests\\TemporaryFileTest::can_use_file_rights":0.001,"ShouldQueueWithoutChainTest::can_import_to_model_in_chunks":0.065,"ShouldQueueWithoutChainTest::can_import_to_model_without_job_chaining":0.053,"ShouldQueueWithoutChainTest::a_queue_name_can_be_specified_when_importing":0.045,"ShouldQueueWithoutChainTest::the_cleanup_only_runs_when_all_jobs_are_done":0.067,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::can_skip_on_error":0.039,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::can_skip_errors_and_collect_all_errors_at_the_end":0.036,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_skip_on_error":0.037,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::skips_only_failed_rows_in_batch":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_skip_failures_and_collect_all_failures_at_the_end":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_validate_using_oneachrow_and_skipsonfailure":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::can_validate_using_tocollection_and_skipsonfailure":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_each_row_to_model":0.058,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::has_timestamps_when_imported_single_model":0.052,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_multiple_models_in_single_to_model":0.06,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_multiple_different_types_of_models_in_single_to_model":0.063,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::can_import_to_model_in_batches":0.074,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::can_import_to_model_in_batches_bigger_file":0.278,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::can_import_multiple_different_types_of_models_in_single_to_model":0.054,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::has_timestamps_when_imported_in_batches":0.056,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_un":0.065,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches":0.436,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row":0.429,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_csv_in_chunks_and_insert_in_batches":1.206,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets":1.223,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_array_in_chunks":1.854,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index":1.216,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name":1.211,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_catch_job_failed_in_chunks":0.048,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_array_and_format_in_chunks":0.054,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::can_import_to_array_in_chunks_without_formatting":0.048,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::can_import_to_array_with_column_limit":0.026,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::can_import_to_array_with_column_limit_and_skips_empty_rows":0.033,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_to_array_with_grouped_headers":0.055,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_oneachrow_with_grouped_headers":0.053,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_to_collection_with_grouped_headers":0.05,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::can_import_each_row_to_model_with_grouped_headers":0.061,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_each_row_to_model_with_heading_row":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_each_row_to_model_with_different_heading_row":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_to_array_with_heading_row":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_empty_rows_with_header":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_import_empty_models_with_header":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::can_cast_empty_headers_to_indexed_int":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::can_import_a_limited_section_of_rows_to_model_with_different_start_row":0.057,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::can_import_to_array_with_limit":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::can_set_limit_bigger_than_row_size":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::can_import_with_references_to_cells":0.034,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::can_import_with_nested_references_to_cells":0.031,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::can_import_with_references_to_cells_to_model":0.041,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::can_import_each_row_to_model_with_different_start_row":0.027,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::can_import_to_array_with_start_row":0.027,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_batches":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_rows":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_batches_with_defined_upsert_columns":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::can_upsert_models_in_rows_with_defined_upsert_columns":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows":0.068,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_closure_validation_rules":0.054,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_custom_validation_rule_objects":0.07,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_conditionality":0.053,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_unless_conditionality":0.056,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_combined_rules_with_colons":0.067,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_with_custom_attributes":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_with_custom_message":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_headings":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_with_grouped_headings":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_rows_in_batches":0.052,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_using_oneachrow":0.05,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_using_collection":0.053,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_validate_using_array":0.129,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_configure_validator":0.059,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_toarray":0.057,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_tocollection":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_tomodel":0.053,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_oneachrow":0.052,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::can_prepare_using_skipsemptyrows":0.06,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::cannot_queue_import_that_does_not_implement_should_queue":0.053,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_an_import":2.07,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_an_import_with_batch_cache_and_file_store":2.129,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_import_with_remote_temp_disk":2.209,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_keep_extension_for_temp_file_on_remote_disk":2.125,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_queue_import_with_remote_temp_disk_and_prefix":2.08,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_automatically_delete_temp_file_on_failure_when_using_remote_disk":0.106,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::cannot_automatically_delete_temp_file_on_failure_when_using_local_disk":0.12,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_force_remote_download_and_deletion_for_each_chunk_on_queue":2.13,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_define_middleware_method_on_queued_import":0.065,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_define_retry_until_method_on_queued_import":0.064,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::can_define_max_exceptions_property_on_queued_import":0.105,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query":0.116,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_relation_query_queued":0.181,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_eager_loads":0.085,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_eager_loads_and_queued":0.106,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_without_using_eloquent":0.063,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_without_using_eloquent_and_queued":0.149,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_with_nested_arrays":0.069,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_builder_with_nested_arrays_queued":0.079,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_batch_caching":0.114,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_query_with_prepare_rows":0.123,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::can_export_from_scout":0.117,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::can_export_from_view":0.041,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::can_export_multiple_sheets_from_view":0.094,"Maatwebsite\\Excel\\Tests\\Concerns\\WithConditionalSheetsTest::can_select_which_sheets_will_be_imported":0.013,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomQuerySizeTest::can_export_with_custom_count":0.09,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_export_with_multiple_sheets_using_collections":0.151,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_export_multiple_sheets_from_view":0.11,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_index_will_throw_sheet_not_found_exception":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_name_will_throw_sheet_not_found_exception":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_name_can_be_ignored":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_name":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_sheet":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets":0.013,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_index_and_name":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name_and_index":0.004,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export":0.208,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache_and_file_store":0.262,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_an_export_with_mapping":0.049,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::can_queue_scout_export":0.228,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::can_queue_an_export":0.145,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::can_export_multiple_sheets_from_view":0.26,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::can_export_from_lazy_collection_with_queue":0.026,"Maatwebsite\\Excel\\Tests\\CellTest::can_get_cell_value":0.029,"Maatwebsite\\Excel\\Tests\\CellTest::can_trim_empty_cells":0.004,"Maatwebsite\\Excel\\Tests\\CellTest::convert_empty_cells_to_null":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::export_chunked_events_get_called":0.113,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportAsMacroTest::can_import_directly_into_a_model_with_mapping":0.036,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportMacroTest::can_import_directly_into_a_model":0.036,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::can_download_a_query_as_excel":0.062,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::can_download_a_collection_with_headers_as_excel":0.061,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::can_download_a_query_as_excel":0.063,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::can_download_a_query_as_excel_on_different_disk":0.061,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::can_store_a_query_with_headers_as_excel":0.07,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_models_with_belongs_to_relations":0.067,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::can_import_models_with_belongs_to_many_relations":0.07,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row":0.005,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_will_get_multiple_from_memory_if_cells_hold_in_memory":0.032,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_will_get_multiple_from_cache_if_cells_are_persisted":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_will_get_multiple_from_cache_and_persisted":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_persists_to_cache_when_memory_limit_reached_on_setting_a_value":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_persists_to_cache_when_memory_limit_reached_on_setting_multiple_values":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_writes_to_cache_with_default_ttl#null (forever)":0.002,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_writes_to_cache_with_default_ttl#int value":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_writes_to_cache_with_default_ttl#callable":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_writes_to_cache_with_a_dateinterval_ttl":0.001,"Maatwebsite\\Excel\\Tests\\Cache\\BatchCacheTest::test_it_can_override_default_ttl":0,"Maatwebsite\\Excel\\Tests\\CellTest::test_can_get_cell_value":0.043,"Maatwebsite\\Excel\\Tests\\CellTest::test_can_trim_empty_cells":0.004,"Maatwebsite\\Excel\\Tests\\CellTest::test_convert_empty_cells_to_null":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_needs_to_have_a_file_name_when_downloading":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_needs_to_have_a_file_name_when_storing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_needs_to_have_a_file_name_when_queuing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_responsable_needs_to_have_file_name_configured_inside_the_export":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_is_responsable":0.037,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_have_customized_header":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_set_custom_headers_in_export_class":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_get_raw_export_contents":0.008,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_have_customized_disk_options_when_storing":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_have_customized_disk_options_when_queueing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_set_disk_options_in_export_class_when_storing":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_set_disk_options_in_export_class_when_queuing":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_override_export_class_disk_options_when_calling_store":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_override_export_class_disk_options_when_calling_queue":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_have_empty_disk_options_when_storing":0,"Maatwebsite\\Excel\\Tests\\Concerns\\ExportableTest::test_can_have_empty_disk_options_when_queueing":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\FromArrayTest::test_can_export_from_array":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::test_can_export_from_collection":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::test_can_export_with_multiple_sheets_from_collection":0.196,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::test_can_export_from_lazy_collection":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\FromCollectionTest::test_can_export_from_lazy_collection_with_queue":0.04,"Maatwebsite\\Excel\\Tests\\Concerns\\FromGeneratorTest::test_can_export_from_generator":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\FromIteratorTest::test_can_export_from_iterator":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query":0.115,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_relation_query_queued":0.183,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_eager_loads":0.085,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_eager_loads_and_queued":0.106,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent":0.07,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent_and_queued":0.149,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays":0.07,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays_queued":0.09,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_batch_caching":0.116,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_query_with_prepare_rows":0.117,"Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest::test_can_export_from_scout":0.144,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::test_can_export_from_view":0.04,"Maatwebsite\\Excel\\Tests\\Concerns\\FromViewTest::test_can_export_multiple_sheets_from_view":0.101,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file":0.008,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file_from_uploaded_file":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_csv_file_with_html_tags_inside":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::test_can_import_each_row_individually":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\OnEachRowTest::test_it_respects_the_end_column":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::test_events_get_called_when_exporting":0.016,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::test_events_get_called_when_importing":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\RegistersEventListenersTest::test_can_have_invokable_class_as_listener":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersChunkOffsetTest::test_can_set_and_get_chunk_offset":0,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersChunkOffsetTest::test_can_access_chunk_offset_on_import_to_array_in_chunks":0.121,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_set_and_get_row_number":0,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_model":0.145,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks":0.086,"Maatwebsite\\Excel\\Tests\\Concerns\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts":0.078,"ShouldQueueWithoutChainTest::test_can_import_to_model_in_chunks":0.065,"ShouldQueueWithoutChainTest::test_can_import_to_model_without_job_chaining":0.046,"ShouldQueueWithoutChainTest::test_a_queue_name_can_be_specified_when_importing":0.051,"ShouldQueueWithoutChainTest::test_the_cleanup_only_runs_when_all_jobs_are_done":0.061,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_collection":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_on_each_row":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_model":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_model":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsEmptyRowsTest::test_custom_skips_rows_when_using_oneachrow":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::test_can_skip_on_error":0.042,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnErrorTest::test_can_skip_errors_and_collect_all_errors_at_the_end":0.037,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_skip_on_error":0.038,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_skips_only_failed_rows_in_batch":0.027,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_skip_failures_and_collect_all_failures_at_the_end":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_validate_using_oneachrow_and_skipsonfailure":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\SkipsOnFailureTest::test_can_validate_using_tocollection_and_skipsonfailure":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::test_can_import_to_array":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\ToArrayTest::test_can_import_multiple_sheets_to_array":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::test_can_import_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\ToCollectionTest::test_can_import_multiple_sheets_to_collection":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_each_row_to_model":0.064,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_has_timestamps_when_imported_single_model":0.055,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_multiple_models_in_single_to_model":0.059,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_multiple_different_types_of_models_in_single_to_model":0.055,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_models_with_belongs_to_relations":0.068,"Maatwebsite\\Excel\\Tests\\Concerns\\ToModelTest::test_can_import_models_with_belongs_to_many_relations":0.076,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBackgroundColorTest::test_can_configure_background_color_from_rgb_string":0.017,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBackgroundColorTest::test_can_configure_background_color_as_array":0.009,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBackgroundColorTest::test_can_configure_background_color_with_color_instance":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_can_import_to_model_in_batches":0.059,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_can_import_to_model_in_batches_bigger_file":0.278,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_can_import_multiple_different_types_of_models_in_single_to_model":0.054,"Maatwebsite\\Excel\\Tests\\Concerns\\WithBatchInsertsTest::test_has_timestamps_when_imported_in_batches":0.058,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_by_default_does_not_calculate_formulas":0.007,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_multi_sheet_references":0.009,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_skips_empty":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas_and_skips_empty":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_un":0.064,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches":0.438,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row":0.441,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_csv_in_chunks_and_insert_in_batches":1.218,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets":1.254,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_array_in_chunks":1.882,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index":1.222,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name":1.219,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_catch_job_failed_in_chunks":0.048,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_array_and_format_in_chunks":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithChunkReadingTest::test_can_import_to_array_in_chunks_without_formatting":0.088,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnFormattingTest::test_can_export_with_column_formatting":0.018,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::test_can_import_to_array_with_column_limit":0.026,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnLimitTest::test_can_import_to_array_with_column_limit_and_skips_empty_rows":0.032,"Maatwebsite\\Excel\\Tests\\Concerns\\WithColumnWidthsTest::test_can_set_column_width":0.016,"Maatwebsite\\Excel\\Tests\\Concerns\\WithConditionalSheetsTest::test_can_select_which_sheets_will_be_imported":0.013,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_can_store_csv_export_with_custom_settings":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_can_store_csv_export_with_custom_encoding":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_can_read_csv_with_auto_detecting_delimiter_semicolon":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_can_read_csv_with_auto_detecting_delimiter_comma":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_can_read_csv_import_with_custom_settings":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomCsvSettingsTest::test_cannot_read_with_wrong_delimiter":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomQuerySizeTest::test_can_export_with_custom_count":0.09,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomStartCellTest::test_can_store_collection_with_custom_start_cell":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::test_can_set_a_value_binder_on_export":0.017,"Maatwebsite\\Excel\\Tests\\Concerns\\WithCustomValueBinderTest::test_can_set_a_value_binder_on_import":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithDefaultStylesTest::test_can_configure_default_styles":0.015,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_export_events_get_called":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_import_events_get_called":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_import_chunked_events_get_called":0.093,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_can_have_invokable_class_as_listener":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_can_have_global_event_listeners":0.009,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_can_have_custom_concern_handlers":0.036,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_can_have_custom_sheet_concern_handlers":0.019,"Maatwebsite\\Excel\\Tests\\Concerns\\WithEventsTest::test_export_chunked_events_get_called":0.002,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_by_default_import_to_array":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_array_with_format_data":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_array_with_format_data_and_skips_empty_rows":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_by_default_import_to_collection":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_collection_with_format_data":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_by_default_import_to_model":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithFormatDataTest::test_can_import_to_model_with_format_data":0.005,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_to_array_with_grouped_headers":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_oneachrow_with_grouped_headers":0.047,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_to_collection_with_grouped_headers":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithGroupedHeadingRowTest::test_can_import_each_row_to_model_with_grouped_headers":0.068,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_each_row_to_model_with_heading_row":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_each_row_to_model_with_different_heading_row":0.032,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_to_array_with_heading_row":0.026,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_empty_rows_with_header":0.03,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_import_empty_models_with_header":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingRowTest::test_can_cast_empty_headers_to_indexed_int":0.025,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::test_can_export_from_collection_with_heading_row":0.017,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::test_can_export_from_collection_with_multiple_heading_rows":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithHeadingsTest::test_can_export_from_collection_with_heading_row_with_custom_start_cell":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::test_can_import_a_limited_section_of_rows_to_model_with_different_start_row":0.033,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::test_can_import_to_array_with_limit":0.026,"Maatwebsite\\Excel\\Tests\\Concerns\\WithLimitTest::test_can_set_limit_bigger_than_row_size":0.025,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::test_can_import_with_references_to_cells":0.026,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::test_can_import_with_nested_references_to_cells":0.026,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappedCellsTest::test_can_import_with_references_to_cells_to_model":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::test_can_export_with_heading":0.018,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::test_can_return_multiple_rows_in_map":0.017,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMappingTest::test_json_array_columns_shouldnt_be_detected_as_multiple_rows":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_export_with_multiple_sheets_using_collections":0.143,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_export_multiple_sheets_from_view":0.11,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_index_will_throw_sheet_not_found_exception":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_name_will_throw_sheet_not_found_exception":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_name_can_be_ignored":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_name":0.003,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_sheet":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name":0.013,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_index_and_name":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name_and_index":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithPropertiesTest::test_can_set_custom_document_properties":0.009,"Maatwebsite\\Excel\\Tests\\Concerns\\WithPropertiesTest::test_it_merges_with_default_properties":0.009,"Maatwebsite\\Excel\\Tests\\Concerns\\WithPropertiesTest::test_it_ignores_empty_properties":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithReadFilterTest::test_can_register_custom_read_filter":0.006,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::test_can_import_each_row_to_model_with_different_start_row":0.027,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStartRowTest::test_can_import_to_array_with_start_row":0.04,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::test_exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison":0.015,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::test_exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison":0.012,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::test_exports_trailing_empty_cells":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStrictNullComparisonTest::test_exports_trailing_empty_cells_by_setting_config_strict_null_comparison":0.004,"Maatwebsite\\Excel\\Tests\\Concerns\\WithStylesTest::test_can_configure_styles":0.017,"Maatwebsite\\Excel\\Tests\\Concerns\\WithTitleTest::test_can_export_with_title":0.01,"Maatwebsite\\Excel\\Tests\\Concerns\\WithTitleTest::test_can_export_sheet_title_when_longer_than_max_length":0.011,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_batches":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_rows":0.041,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_batches_with_defined_upsert_columns":0.029,"Maatwebsite\\Excel\\Tests\\Concerns\\WithUpsertsTest::test_can_upsert_models_in_rows_with_defined_upsert_columns":0.028,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_closure_validation_rules":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_custom_validation_rule_objects":0.052,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_conditionality":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_unless_conditionality":0.052,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_combined_rules_with_colons":0.069,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_with_custom_attributes":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_with_custom_message":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_headings":0.055,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_with_grouped_headings":0.049,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_rows_in_batches":0.05,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_using_oneachrow":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_using_collection":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_validate_using_array":0.048,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_configure_validator":0.057,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_toarray":0.05,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_tocollection":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_tomodel":0.051,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_oneachrow":0.05,"Maatwebsite\\Excel\\Tests\\Concerns\\WithValidationTest::test_can_prepare_using_skipsemptyrows":0.049,"Maatwebsite\\Excel\\Tests\\DelegatedMacroableTest::test_can_call_methods_from_delegate":0.009,"Maatwebsite\\Excel\\Tests\\DelegatedMacroableTest::test_can_use_writer_macros":0.01,"Maatwebsite\\Excel\\Tests\\DelegatedMacroableTest::test_can_use_sheet_macros":0.008,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_fake_an_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_downloaded_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_stored_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_regex_against_a_fake_stored_export_with_multiple_files":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_stored_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_queued_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_implicitly_queued_export":0,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_queued_export_with_chain":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_raw_export":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_import":0.004,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_import_with_uploaded_file":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_queued_import":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_implicitly_queued_import":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_can_assert_against_a_fake_queued_import_with_chain":0.001,"Maatwebsite\\Excel\\Tests\\ExcelFakeTest::test_a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_queued_export":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::test_custom_transaction_handler_is_bound":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::test_is_bound":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::test_has_aliased":0,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::test_registers_console_commands":0.008,"Maatwebsite\\Excel\\Tests\\ExcelServiceProviderTest::test_sets_php_spreadsheet_settings":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_download_an_export_object_with_facade":0.008,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_download_an_export_object":0.007,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_store_an_export_object_on_default_disk":0.01,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_store_an_export_object_on_another_disk":0.012,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_store_csv_export_with_default_settings":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_get_raw_export_contents":0.012,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_store_tsv_export_with_default_settings":0.002,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_store_csv_export_with_custom_settings":0.002,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_cannot_use_from_collection_and_from_view_on_same_export":0.002,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_to_array":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_to_collection":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_to_collection_without_import_object":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_tsv_file":0.009,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_chain_imports":0.003,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_from_uploaded_file":0.005,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_a_simple_xlsx_file_from_real_path":0.005,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_import_will_throw_error_when_no_reader_type_could_be_detected_when_no_extension":0.001,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_import_will_throw_error_when_no_reader_type_could_be_detected_with_unknown_extension":0.035,"Maatwebsite\\Excel\\Tests\\ExcelTest::test_can_import_without_extension_with_explicit_reader_type":0.004,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row_with_custom_heading_row_formatter":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row_with_custom_heading_row_formatter_with_key":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row_with_custom_row_number":0.005,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row_for_multiple_sheets":0.003,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row_for_multiple_sheets_with_key":0.005,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_only_heading_row_for_multiple_sheets_with_custom_row_number":0.004,"Maatwebsite\\Excel\\Tests\\HeadingRowImportTest::test_can_import_heading_row_with_custom_formatter_defined_in_config":0.004,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::test_read_chunk_job_can_interact_with_queue":0.001,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::test_append_data_to_sheet_job_can_interact_with_queue":0,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::test_append_query_to_sheet_job_can_interact_with_queue":0.001,"Maatwebsite\\Excel\\Tests\\InteractsWithQueueTest::test_append_view_to_sheet_job_can_interact_with_queue":0.001,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::test_can_download_a_collection_as_excel":0.011,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::test_can_download_a_collection_with_headers_as_excel":0.011,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::test_can_download_collection_with_headers_with_hidden_eloquent_attributes":0.011,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::test_can_download_collection_with_headers_when_making_attributes_visible":0.011,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadCollectionTest::test_can_set_custom_response_headers":0.008,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::test_can_download_a_query_as_excel":0.058,"Maatwebsite\\Excel\\Tests\\Mixins\\DownloadQueryMacroTest::test_can_download_a_collection_with_headers_as_excel":0.062,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportAsMacroTest::test_can_import_directly_into_a_model_with_mapping":0.032,"Maatwebsite\\Excel\\Tests\\Mixins\\ImportMacroTest::test_can_import_directly_into_a_model":0.035,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::test_can_store_a_collection_as_excel":0.012,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::test_can_store_a_collection_as_excel_on_non_default_disk":0.01,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::test_can_store_a_collection_with_headings_as_excel":0.01,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreCollectionTest::test_can_store_a_model_collection_with_headings_as_excel":0,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::test_can_download_a_query_as_excel":0.061,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::test_can_download_a_query_as_excel_on_different_disk":0.059,"Maatwebsite\\Excel\\Tests\\Mixins\\StoreQueryMacroTest::test_can_store_a_query_with_headers_as_excel":0.065,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_queue_an_export":0.365,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_queue_an_export_and_store_on_different_disk":0.349,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_queue_export_with_remote_temp_disk":0.444,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_queue_export_with_remote_temp_disk_and_prefix":0.335,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_implicitly_queue_an_export":0.332,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_queue_export_with_mapping_on_eloquent_models":0.029,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_catch_failures":0.01,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_catch_failures_on_queue_export_job":0.003,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_set_locale_on_queue_export_job":0.03,"Maatwebsite\\Excel\\Tests\\QueuedExportTest::test_can_queue_export_not_flushing_the_cache":0.385,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_cannot_queue_import_that_does_not_implement_should_queue":0.046,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_an_import":2.07,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_an_import_with_batch_cache_and_file_store":3.877,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk":2.219,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_keep_extension_for_temp_file_on_remote_disk":2.262,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk_and_prefix":2.062,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_automatically_delete_temp_file_on_failure_when_using_remote_disk":0.108,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_cannot_automatically_delete_temp_file_on_failure_when_using_local_disk":0.106,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_force_remote_download_and_deletion_for_each_chunk_on_queue":2.176,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_define_middleware_method_on_queued_import":0.067,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_define_retry_until_method_on_queued_import":0.064,"Maatwebsite\\Excel\\Tests\\QueuedImportTest::test_can_define_max_exceptions_property_on_queued_import":0.106,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_an_export":0.205,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_an_export_with_batch_cache_and_file_store":3.691,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_an_export_with_mapping":0.051,"Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest::test_can_queue_scout_export":0.372,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::test_can_queue_an_export":0.138,"Maatwebsite\\Excel\\Tests\\QueuedViewExportTest::test_can_export_multiple_sheets_from_view":0.266,"Maatwebsite\\Excel\\Tests\\TemporaryFileTest::test_can_use_default_rights":0.002,"Maatwebsite\\Excel\\Tests\\TemporaryFileTest::test_can_use_dir_rights":0.001,"Maatwebsite\\Excel\\Tests\\TemporaryFileTest::test_can_use_file_rights":0.001,"Maatwebsite\\Excel\\Tests\\Concerns\\ImportableTest::test_cannot_import_a_non_existing_xlsx_file":0.001,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_array_input":0.025,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_object_input":0,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_callable_input":0,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_string_input_matching_pattern":0.006,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_string_input_not_matching_pattern":0,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_required_without_all":0.006,"Maatwebsite\\Excel\\Tests\\Validators\\RowValidatorTest::test_format_rule_with_required_without":0}}
================================================
FILE: .styleci.yml
================================================
preset: laravel
risky: false
enabled:
- align_double_arrow
- align_equals
- concat_with_spaces
- ordered_class_elements
disabled:
- concat_without_spaces
- not_operator_with_successor_space
- unalign_equals
finder:
not-name:
- "*.md"
not-path:
- ".github"
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
Please view https://github.com/SpartnerNL/Laravel-Excel/releases for the most recent changelog
## [3.1.47] - 2023-02-16
- Support Laravel 10
### Fixed
- Fix Bug Multiple drawings change the behavior of the startCell (#3865).
- Allow configuring read data only in chunks as well.
## [3.1.46] - 2023-01-27
- Support Laravel 10
## [3.1.45] - 2023-01-02
### Added
- Add support for ignoring PHP auto_detect_line_endings INI directive
### Fixed
- Fix the PSR simple cache dependency mess to maintain backwards compatibility and support 3.0 of the interface.
## [3.1.44] - 2022-10-14
### Fixed
- Fix output of `WithFormatData` in combination with `SkipsEmptyRows` (#3760)
### Changed
- Cast empty headings to indexed integer (#3646)
- Adds `isEmptyWhen` to customize is row empty logic. (#3645)
### Fixed
- Fix temporary local files not being cleaned up when setting force_resync_remote config to true (#3623)
- Fix testing for multiple stored files by regex matching (#3631).
- Allow `required_unless` rule (#3660)
## [3.1.40] - 2022-05-02
- Fix testing for multiple stored files by regex matching (#3631).
### Changed
- Adds `WithDefaultStyles` concern to allow configuring the workbook default styles.
- Adds `WithBackgroundColor` concern to allow configuring the workbook default background color.
- Expose the ability to set custom response headers when exporting collections via Exportable
## [3.1.39] - 2022-04-23
### Fixed
- Fix PHP8.1 return type for Failure class (#3588)
## [3.1.38] - 2022-03-24
### Changed
- Adds concern `WithGroupedHeadingRow` to allow imported sheets to group the values of columns with the same header in an array
### Fixed
- Fix for `prepareForValidation` callback not being called when using `SkipsEmptyRows`
## [3.1.37] - 2022-02-28
### Fixed
- Add `@mixin` docblock to all macroable classes to allow for IDE autocompletion of delegate classes
- Fix issue with `Excel::toArray` not allowing nullable reader types for uploaded files
### Changed
- Change default Csv Import to auto-detect the delimiter when not explicitly defined
## [3.1.36] - 2022-02-03
### Fixed
- Fix return type of `FromQuery::query()`
### Changed
- Support Laravel 9
- Added a config setting to specify DB connection
- Added a config setting to specify CSV output encoding
- Added an ability to specify CSV output encoding through csvSettings
## [3.1.35] - 2022-01-04
### Fixed
- Removed cache flush for cell caching as this is already handled by PhpSpreadsheet
- Fix `SkipsEmptyRows` support with the `WithColumnLimit` concern
- Added range support to FormatColumn
## [3.1.34] - 2021-12-2
### Changed
- Change default local_path configuration
- Fix queueImport function to be able to assert chained jobs
- Skipped failure no longer persists in `ToCollection` and `ToArray`.
- Fix missing InteractsWithQueue trait in AppendToSheet jobs
- Add return types to `Row`'s `ArrayAccess` implementation
## [3.1.33] - 2021-08-12
### Fixed
- Make TransactionManager a singleton (#3270)
- Fix Exportable disk options (#3296)
- Delete temporary file after exception in import class (#3312)
## [3.1.32] - 2021-07-08
### Added
- Add assertExportedInRaw assertion (#3255)
### Fixed
- Make commands detect model directory now (#3213)
## [3.1.31] - 2021-06-02
### Added
- Custom heading row formatter can use column index (#3166)
- Added WithFormatData concern (#3154)
### Fixed
- Create failures of rows than didn't exist but where requested in row
validation
- Fix Bug Formulas are not calculated when import implements
WithCalculatedFormulas with SkipsEmptyRows #3127
- PhpSpreadsheet 1.18 support
## [3.1.30] - 2021-04-06
### Added
- Octane compatibility
## [3.1.29] - 2021-03-16
### Fixed
- Fix AfterImport Event not being called (#3085)
## [3.1.28] - 2021-03-10
### Added
- Added WithUpsertColumns concern (#3046)
- Added ShouldQueueWithoutChain concern (#3072)
### Fixed
- Limit Phpspreadsheet version to 1.16 until bugfix release
- Fixed issue with not autosizing columns (#3055)
- Fix selecting worksheets by name with chunk reading (#3052)
## [3.1.27] - 2021-02-22
### Added
- Added SkipsEmptyRows concern
- Added HasReferencesToOtherSheets concern to allow import of calculated
### Changed
- Bump minimum PhpSpreadsheet version
- Progressbar NullOutput as fallback
## [3.1.26] - 2020-11-13
### Added
- PHP 8 support
## [3.1.25] - 2020-11-13
### Added
- Added an ability to prepare rows before appending rows to sheet. Just add
`prepareRows` method for your export class if needed.
- Added an ability to catch exceptions from `QueueExport` job. Just add `failed`
method for your export class if needed.
- Added an ability to set locale for queued export. Just implement
`Illuminate\Contracts\Translation\HasLocalePreference` for your export.
- Added `JsonSerializable` support in `Maatwebsite\Excel\Validators\Failure`.
- Added `$maxExceptions` support in `Maatwebsite\Excel\Jobs\ReadChunk.php`.
- Added support to upsert models by implementing the `WithUpserts` concern.
## [3.1.24] - 2020-10-28
### Added
- Added support for `prepareForValidation` on `WithValidation` concern
- Added support for `withValidator` on `WithValidation` concern
- Added `ArrayAccess` to `Row`
### Fixed
- Corrected SkipsErrors doc block
## [3.1.23] - 2020-09-29
### Added
- Added `ignore_empty` setting to `config/excel.php`
- Added `strict_null_comparison` setting to `config/excel.php`
## [3.1.22] - 2020-09-08
- Laravel 8 support
- Lumen improvements
## [3.1.21] - 2020-08-06
### Added
- Added WithProperties concern
- Added default spreadsheet properties config
- Added WithColumnWidths concern
- Added WithStyles concern.
- Config setting to configure cell caching
### Changed
- Sheet titles longer than 31 chars get trimmed.
- Sheet titles with unsupported chars get cleaned.
### Fixed
- Fixed issue with using ShouldAutosize in combination with FromView column
widths.
## [3.1.20] - 2020-07-22
### Added
- Re-sycing remote temporary file
- Remember row number
- Remember chunk offset
- WithColumnLimit concern
- WithReadFilter concern
- Publishing the stubs
### Changed
- Interacting with queued jobs
- Retry until and middleware on queued imports
- Using WithValidation with FromCollection & FromArray
- Read filters for WithLimit and HeadingRowImport
- Bump of minimum version PhpSpreadsheet
### Fixed
- Fixed test helper docblocks on the Excel facade.
- Fix for importing with a start row beyond the highest row.
- Fixed `BeforeSheet` and `AfterSheet` events receiving exportable instance
instead of importable when calling on an Import.
- Fix for value binders not working in queued exports.
- Fix when using WithLimit concern when having less rows than the limit.
- Fix AfterImport job being fired twice if not using queueing.
- Raw() method now also available on Exportable.
- Fix for breaking changes in PhpSpreadsheet with empty enclosures.
[Unreleased]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.47...HEAD
[3.1.47]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.46...3.1.47
[3.1.46]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.45...3.1.46
[3.1.45]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.44...3.1.45
[3.1.44]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.43...3.1.44
[3.1.43]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.42...3.1.43
[3.1.42]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.41...3.1.42
[3.1.41]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.40...3.1.41
[3.1.40]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.39...3.1.40
[3.1.39]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.38...3.1.39
[3.1.38]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.37...3.1.38
[3.1.37]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.36...3.1.37
[3.1.36]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.35...3.1.36
[3.1.35]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.34...3.1.35
[3.1.34]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.33...3.1.34
[3.1.33]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.32...3.1.33
[3.1.32]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.31...3.1.32
[3.1.31]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.30...3.1.31
[3.1.30]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.29...3.1.30
[3.1.29]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.28...3.1.29
[3.1.28]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.27...3.1.28
[3.1.27]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.26...3.1.27
[3.1.26]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.25...3.1.26
[3.1.25]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.24...3.1.25
[3.1.24]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.23...3.1.24
[3.1.23]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.22...3.1.23
[3.1.22]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.21...3.1.22
[3.1.21]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.20...3.1.21
[3.1.20]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.19...3.1.20
_Older release notes can be found in Github releases._
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at patrick@spartner.nl. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
Find the contributing guide at: https://docs.laravel-excel.com/3.1/getting-started/contributing.html
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) Spartner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
A simple, but elegant Laravel wrapper around PhpSpreadsheet exports and imports.
row2
'], ['key3', 'C', 'row3'], ['key4', 'D', 'row4'], ['key5', 'E', 'row5'], ['key6', 'F', 'link"'], ], $array); } }; $import->import('csv-with-html-tags.csv', 'local', Excel::CSV); } public function test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true() { config()->set('excel.imports.ignore_empty', true); $import = new class implements ToArray { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ ['test', 'test'], ['test', 'test'], ], $array); } }; $imported = $import->import('import-with-some-empty-rows.xlsx'); $this->assertInstanceOf(Importer::class, $imported); } public function test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false() { config()->set('excel.imports.ignore_empty', false); $import = new class implements ToArray { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ ['test', 'test'], ['test', 'test'], ['', ''], ['', ''], ], $array); } }; $imported = $import->import('import-with-some-empty-rows.xlsx'); $this->assertInstanceOf(Importer::class, $imported); } public function test_cannot_import_a_non_existing_xlsx_file() { $this->expectException(FileNotFoundException::class); $import = new class { use Importable; }; $import->import('doesnotexistanywhere.xlsx'); } } ================================================ FILE: tests/Concerns/OnEachRowTest.php ================================================ getCellIterator() as $cell) { Assert::assertEquals('test', $cell->getValue()); } Assert::assertEquals([ 'test', 'test', ], $row->toArray()); Assert::assertEquals('test', $row[0]); $this->called++; } }; $import->import('import.xlsx'); $this->assertEquals(2, $import->called); } public function test_it_respects_the_end_column() { $import = new class implements OnEachRow { use Importable; /** * @param Row $row */ public function onRow(Row $row) { // Accessing a row as an array calls toArray() without an end // column. This saves the row in the cache, so we have to // invalidate the cache once the end column changes $row[0]; Assert::assertEquals([ 'test', ], $row->toArray(null, false, true, 'A')); } }; $import->import('import.xlsx'); } } ================================================ FILE: tests/Concerns/RegistersEventListenersTest.php ================================================ assertInstanceOf(BeforeExport::class, $event); $this->assertInstanceOf(Writer::class, $event->writer); $eventsTriggered++; }; $event::$beforeWriting = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeWriting::class, $event); $this->assertInstanceOf(Writer::class, $event->writer); $eventsTriggered++; }; $event::$beforeSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->sheet); $eventsTriggered++; }; $event::$afterSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(AfterSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->sheet); $eventsTriggered++; }; $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx')); $this->assertEquals(4, $eventsTriggered); } public function test_events_get_called_when_importing() { $event = new ImportWithRegistersEventListeners(); $eventsTriggered = 0; $event::$beforeImport = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeImport::class, $event); $this->assertInstanceOf(Reader::class, $event->reader); $eventsTriggered++; }; $event::$beforeSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->sheet); $eventsTriggered++; }; $event::$afterSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(AfterSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->sheet); $eventsTriggered++; }; $event->import('import.xlsx'); $this->assertEquals(3, $eventsTriggered); } public function test_can_have_invokable_class_as_listener() { $event = new ExportWithEvents(); $event->beforeExport = new BeforeExportListener(function ($event) { $this->assertInstanceOf(BeforeExport::class, $event); $this->assertInstanceOf(Writer::class, $event->writer); }); $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx')); } } ================================================ FILE: tests/Concerns/RemembersChunkOffsetTest.php ================================================ setChunkOffset(50); $this->assertEquals(50, $import->getChunkOffset()); } public function test_can_access_chunk_offset_on_import_to_array_in_chunks() { $import = new class implements ToArray, WithChunkReading { use Importable; use RemembersChunkOffset; public $offsets = []; public function array(array $array) { $this->offsets[] = $this->getChunkOffset(); } public function chunkSize(): int { return 2000; } }; $import->import('import-batches.xlsx'); $this->assertEquals([1, 2001, 4001], $import->offsets); } } ================================================ FILE: tests/Concerns/RemembersRowNumberTest.php ================================================ rememberRowNumber(50); $this->assertEquals(50, $import->getRowNumber()); } public function test_can_access_row_number_on_import_to_model() { $import = new class implements ToModel { use Importable; use RemembersRowNumber; public $rowNumbers = []; public function model(array $row) { $this->rowNumbers[] = $this->getRowNumber(); } }; $import->import('import-batches.xlsx'); $this->assertEquals([46, 47, 48, 49, 50, 51, 52, 53, 54, 55], array_slice($import->rowNumbers, 45, 10)); } public function test_can_access_row_number_on_import_to_array_in_chunks() { $import = new class implements ToModel, WithChunkReading { use Importable; use RemembersRowNumber; public $rowNumbers = []; public function chunkSize(): int { return 50; } public function model(array $row) { $this->rowNumbers[] = $this->getRowNumber(); } }; $import->import('import-batches.xlsx'); $this->assertEquals([46, 47, 48, 49, 50, 51, 52, 53, 54, 55], array_slice($import->rowNumbers, 45, 10)); } public function test_can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts() { $import = new class implements ToModel, WithChunkReading, WithBatchInserts { use Importable; use RemembersRowNumber; public $rowNumbers = []; public function chunkSize(): int { return 50; } public function model(array $row) { $this->rowNumbers[] = $this->rowNumber; } public function batchSize(): int { return 50; } }; $import->import('import-batches.xlsx'); $this->assertEquals([46, 47, 48, 49, 50, 51, 52, 53, 54, 55], array_slice($import->rowNumbers, 45, 10)); } } ================================================ FILE: tests/Concerns/ShouldQueueWithoutChainTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); } public function test_can_import_to_model_in_chunks() { DB::connection()->enableQueryLog(); $import = new QueueImportWithoutJobChaining(); $import->import('import-users.xlsx'); $this->assertCount(2, DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_to_model_without_job_chaining() { Queue::fake(); $import = new QueueImportWithoutJobChaining(); $import->import('import-users.xlsx'); Queue::assertPushed(ReadChunk::class, 2); Queue::assertPushed(AfterImportJob::class, 1); Queue::assertPushed(AfterImportJob::class, function ($import) { return !is_null($import->delay); }); Queue::assertNotPushed(QueueImport::class); } public function test_a_queue_name_can_be_specified_when_importing() { Queue::fake(); $import = new QueueImportWithoutJobChaining(); $import->queue = 'queue-name'; $import->import('import-users.xlsx'); Queue::assertPushedOn('queue-name', ReadChunk::class); Queue::assertPushedOn('queue-name', AfterImportJob::class); } public function test_the_cleanup_only_runs_when_all_jobs_are_done() { $fake = Queue::fake(); if (method_exists($fake, 'serializeAndRestore')) { $fake->serializeAndRestore(); // More realism } $import = new QueueImportWithoutJobChaining(); $import->import('import-users.xlsx'); $jobs = Queue::pushedJobs(); $chunks = collect($jobs[ReadChunk::class])->pluck('job'); $chunks->each(function (ReadChunk $chunk) { self::assertFalse(ReadChunk::isComplete($chunk->getUniqueId())); }); self::assertCount(2, $chunks); $afterImport = $jobs[AfterImportJob::class][0]['job']; if (!method_exists($fake, 'except')) { /** @var SyncQueue $queue */ $fake = app(SyncQueue::class); $fake->setContainer(app()); } else { $fake->except([AfterImportJob::class, ReadChunk::class]); } $fake->push($chunks->first()); self::assertTrue(ReadChunk::isComplete($chunks->first()->getUniqueId())); self::assertFalse(ReadChunk::isComplete($chunks->last()->getUniqueId())); Event::listen(JobProcessed::class, function (JobProcessed $event) { self::assertTrue($event->job->isReleased()); }); $fake->push($afterImport); Event::forget(JobProcessed::class); $fake->push($chunks->last()); Event::listen(JobProcessed::class, function (JobProcessed $event) { self::assertFalse($event->job->isReleased()); }); $fake->push($afterImport); Event::forget(JobProcessed::class); } } ================================================ FILE: tests/Concerns/SkipsEmptyRowsTest.php ================================================ called = true; Assert::assertEquals([ ['Test1', 'Test2'], ['Test3', 'Test4'], ['Test5', 'Test6'], ], $collection->toArray()); } }; $import->import('import-empty-rows.xlsx'); $this->assertTrue($import->called); } public function test_skips_empty_rows_when_importing_on_each_row() { $import = new class implements OnEachRow, SkipsEmptyRows { use Importable; public $rows = 0; /** * @param Row $row */ public function onRow(Row $row) { Assert::assertFalse($row->isEmpty()); $this->rows++; } }; $import->import('import-empty-rows.xlsx'); $this->assertEquals(3, $import->rows); } public function test_skips_empty_rows_when_importing_to_model() { $import = new class implements ToModel, SkipsEmptyRows { use Importable; public $rows = 0; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { $this->rows++; return null; } }; $import->import('import-empty-rows.xlsx'); $this->assertEquals(3, $import->rows); } public function test_custom_skips_rows_when_importing_to_collection() { $import = new class implements SkipsEmptyRows, ToCollection { use Importable; public $called = false; /** * @param Collection $collection */ public function collection(Collection $collection) { $this->called = true; Assert::assertEquals([ ['Test1', 'Test2'], ['Test3', 'Test4'], ], $collection->toArray()); } public function isEmptyWhen(array $row) { return $row[0] == 'Test5' && $row[1] == 'Test6'; } }; $import->import('import-empty-rows.xlsx'); $this->assertTrue($import->called); } public function test_custom_skips_rows_when_importing_to_model() { $import = new class implements SkipsEmptyRows, ToModel { use Importable; public $called = false; /** * @param array $row */ public function model(array $row) { Assert::assertEquals('Not empty', $row[0]); } public function isEmptyWhen(array $row): bool { $this->called = true; return $row[0] === 'Empty'; } }; $import->import('skip-empty-rows-with-is-empty-when.xlsx'); $this->assertTrue($import->called); } public function test_custom_skips_rows_when_using_oneachrow() { $import = new class implements SkipsEmptyRows, OnEachRow { use Importable; public $called = false; /** * @param array $row */ public function onRow(Row $row) { Assert::assertEquals('Not empty', $row[0]); } public function isEmptyWhen(array $row): bool { $this->called = true; return $row[0] === 'Empty'; } }; $import->import('skip-empty-rows-with-is-empty-when.xlsx'); $this->assertTrue($import->called); } } ================================================ FILE: tests/Concerns/SkipsOnErrorTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_skip_on_error() { $import = new class implements ToModel, SkipsOnError { use Importable; public $errors = 0; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @param Throwable $e */ public function onError(Throwable $e) { Assert::assertInstanceOf(QueryException::class, $e); Assert::stringContains($e->getMessage(), 'Duplicate entry \'patrick@maatwebsite.nl\''); $this->errors++; } }; $import->import('import-users-with-duplicates.xlsx'); $this->assertEquals(1, $import->errors); // Shouldn't have rollbacked other imported rows. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_skip_errors_and_collect_all_errors_at_the_end() { $import = new class implements ToModel, SkipsOnError { use Importable, SkipsErrors; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } }; $import->import('import-users-with-duplicates.xlsx'); $this->assertCount(1, $import->errors()); /** @var Throwable $e */ $e = $import->errors()->first(); $this->assertInstanceOf(QueryException::class, $e); $this->stringContains($e->getMessage(), 'Duplicate entry \'patrick@maatwebsite.nl\''); // Shouldn't have rollbacked other imported rows. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_skip_on_error_when_using_oneachrow_with_validation() { $import = new class implements OnEachRow, WithValidation, SkipsOnError { use Importable; public $errors = 0; public $processedRows = 0; /** * @param Row $row */ public function onRow(Row $row) { $this->processedRows++; // This will be called for valid rows $rowArray = $row->toArray(); User::create([ 'name' => $rowArray[0], 'email' => $rowArray[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } /** * @param Throwable $e */ public function onError(Throwable $e) { Assert::assertInstanceOf(ValidationException::class, $e); Assert::stringContains($e->getMessage(), 'The selected 1 is invalid'); $this->errors++; } }; $import->import('import-users.xlsx'); $this->assertEquals(1, $import->errors); $this->assertEquals(1, $import->processedRows); // Only the valid row should be processed // Should have inserted the valid row $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting the invalid row $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_skip_errors_and_collect_all_errors_when_using_oneachrow_with_validation() { $import = new class implements OnEachRow, WithValidation, SkipsOnError { use Importable, SkipsErrors; public $processedRows = 0; /** * @param Row $row */ public function onRow(Row $row) { $this->processedRows++; // This will be called for valid rows $rowArray = $row->toArray(); User::create([ 'name' => $rowArray[0], 'email' => $rowArray[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; $import->import('import-users.xlsx'); $this->assertCount(1, $import->errors()); $this->assertEquals(1, $import->processedRows); // Only the valid row should be processed /** @var Throwable $e */ $e = $import->errors()->first(); $this->assertInstanceOf(ValidationException::class, $e); $this->stringContains($e->getMessage(), 'The selected 1 is invalid'); // Should have inserted the valid row $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting the invalid row $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_skip_on_error_when_exception_thrown_in_onrow() { $import = new class implements OnEachRow, SkipsOnError { use Importable; public $errors = 0; public $processedRows = 0; /** * @param Row $row */ public function onRow(Row $row) { $this->processedRows++; $rowArray = $row->toArray(); // Throw an exception for the second row (Taylor Otwell) if ($rowArray[1] === 'taylor@laravel.com') { throw new \Exception('Custom error in onRow for Taylor'); } User::create([ 'name' => $rowArray[0], 'email' => $rowArray[1], 'password' => 'secret', ]); } /** * @param Throwable $e */ public function onError(Throwable $e) { Assert::assertInstanceOf(\Exception::class, $e); Assert::assertEquals('Custom error in onRow for Taylor', $e->getMessage()); $this->errors++; } }; $import->import('import-users.xlsx'); $this->assertEquals(1, $import->errors); $this->assertEquals(2, $import->processedRows); // Both rows should be processed, but one throws exception // Should have inserted the valid row $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting the row that threw exception $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_skip_errors_and_collect_all_errors_when_exception_thrown_in_onrow() { $import = new class implements OnEachRow, SkipsOnError { use Importable, SkipsErrors; public $processedRows = 0; /** * @param Row $row */ public function onRow(Row $row) { $this->processedRows++; $rowArray = $row->toArray(); // Throw an exception for the second row (Taylor Otwell) if ($rowArray[1] === 'taylor@laravel.com') { throw new \RuntimeException('Runtime error in onRow for Taylor'); } User::create([ 'name' => $rowArray[0], 'email' => $rowArray[1], 'password' => 'secret', ]); } }; $import->import('import-users.xlsx'); $this->assertCount(1, $import->errors()); $this->assertEquals(2, $import->processedRows); // Both rows should be processed, but one throws exception /** @var Throwable $e */ $e = $import->errors()->first(); $this->assertInstanceOf(\RuntimeException::class, $e); $this->assertEquals('Runtime error in onRow for Taylor', $e->getMessage()); // Should have inserted the valid row $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting the row that threw exception $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } } ================================================ FILE: tests/Concerns/SkipsOnFailureTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_skip_on_error() { $import = new class implements ToModel, WithValidation, SkipsOnFailure { use Importable; public $failures = 0; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } /** * @param Failure[] $failures */ public function onFailure(Failure ...$failures) { $failure = $failures[0]; Assert::assertEquals(2, $failure->row()); Assert::assertEquals('1', $failure->attribute()); Assert::assertEquals(['The selected 1 is invalid.'], $failure->errors()); Assert::assertEquals(['Taylor Otwell', 'taylor@laravel.com'], $failure->values()); Assert::assertEquals(2, $failure->jsonSerialize()['row']); Assert::assertEquals('1', $failure->jsonSerialize()['attribute']); Assert::assertEquals(['The selected 1 is invalid.'], $failure->jsonSerialize()['errors']); Assert::assertEquals(['Taylor Otwell', 'taylor@laravel.com'], $failure->jsonSerialize()['values']); $this->failures += \count($failures); } }; $import->import('import-users.xlsx'); $this->assertEquals(1, $import->failures); // Shouldn't have rollbacked other imported rows. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_skips_only_failed_rows_in_batch() { $import = new class implements ToModel, WithValidation, WithBatchInserts, SkipsOnFailure { use Importable; public $failures = 0; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } /** * @param Failure[] $failures */ public function onFailure(Failure ...$failures) { $failure = $failures[0]; Assert::assertEquals(2, $failure->row()); Assert::assertEquals('1', $failure->attribute()); Assert::assertEquals(['The selected 1 is invalid.'], $failure->errors()); $this->failures += \count($failures); } /** * @return int */ public function batchSize(): int { return 100; } }; $import->import('import-users.xlsx'); $this->assertEquals(1, $import->failures); // Shouldn't have rollbacked/skipped the rest of the batch. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_skip_failures_and_collect_all_failures_at_the_end() { $import = new class implements ToModel, WithValidation, SkipsOnFailure { use Importable, SkipsFailures; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; $import->import('import-users.xlsx'); $this->assertCount(1, $import->failures()); /** @var Failure $failure */ $failure = $import->failures()->first(); $this->assertEquals(2, $failure->row()); $this->assertEquals('1', $failure->attribute()); $this->assertEquals(['The selected 1 is invalid.'], $failure->errors()); // Shouldn't have rollbacked other imported rows. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_validate_using_oneachrow_and_skipsonfailure() { $import = new class implements OnEachRow, WithValidation, SkipsOnFailure { use Importable, SkipsFailures; /** * @param Row $row * @return Model|null */ public function onRow(Row $row) { $row = $row->toArray(); return User::create([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; $this->assertEmpty(User::all()); $import->import('import-users.xlsx'); $this->assertCount(1, $import->failures()); // Shouldn't have rollbacked other imported rows. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } public function test_can_validate_using_tocollection_and_skipsonfailure() { $import = new class implements ToCollection, WithValidation, SkipsOnFailure { use Importable, SkipsFailures; /** * @param Row $row * @return Model|null */ public function collection(Collection $rows) { $rows = $rows->each(function ($row) { return User::create([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); }); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; $this->assertEmpty(User::all()); $import->import('import-users.xlsx'); $this->assertCount(1, $import->failures()); // Shouldn't have rollbacked other imported rows. $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); // Should have skipped inserting $this->assertDatabaseMissing('users', [ 'email' => 'taylor@laravel.com', ]); } } ================================================ FILE: tests/Concerns/ToArrayTest.php ================================================ called = true; Assert::assertEquals([ ['test', 'test'], ['test', 'test'], ], $array); } }; $import->import('import.xlsx'); $this->assertTrue($import->called); } public function test_can_import_multiple_sheets_to_array() { $import = new class implements ToArray { use Importable; public $called = 0; /** * @param array $array */ public function array(array $array) { $this->called++; $sheetNumber = $this->called; Assert::assertEquals([ [$sheetNumber . '.A1', $sheetNumber . '.B1'], [$sheetNumber . '.A2', $sheetNumber . '.B2'], ], $array); } }; $import->import('import-multiple-sheets.xlsx'); $this->assertEquals(2, $import->called); } } ================================================ FILE: tests/Concerns/ToCollectionTest.php ================================================ called = true; Assert::assertEquals([ ['test', 'test'], ['test', 'test'], ], $collection->toArray()); } }; $import->import('import.xlsx'); $this->assertTrue($import->called); } public function test_can_import_multiple_sheets_to_collection() { $import = new class implements ToCollection { use Importable; public $called = 0; /** * @param Collection $collection */ public function collection(Collection $collection) { $this->called++; $sheetNumber = $this->called; Assert::assertEquals([ [$sheetNumber . '.A1', $sheetNumber . '.B1'], [$sheetNumber . '.A2', $sheetNumber . '.B2'], ], $collection->toArray()); } }; $import->import('import-multiple-sheets.xlsx'); $this->assertEquals(2, $import->called); } } ================================================ FILE: tests/Concerns/ToModelTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); } public function test_can_import_each_row_to_model() { DB::connection()->enableQueryLog(); $import = new class implements ToModel { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } }; $import->import('import-users.xlsx'); $this->assertCount(2, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ]); } public function test_has_timestamps_when_imported_single_model() { $import = new class implements ToModel { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } }; $import->import('import-users.xlsx'); $user = User::first(); $this->assertNotNull($user->created_at); $this->assertNotNull($user->updated_at); } public function test_can_import_multiple_models_in_single_to_model() { DB::connection()->enableQueryLog(); $import = new class implements ToModel { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { $user1 = new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); $faker = Factory::create(); $user2 = new User([ 'name' => $faker->name, 'email' => $faker->email, 'password' => 'secret', ]); return [$user1, $user2]; } }; $import->import('import-users.xlsx'); $this->assertCount(4, DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_multiple_different_types_of_models_in_single_to_model() { DB::connection()->enableQueryLog(); $import = new class implements ToModel { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { $user = new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); $group = new Group([ 'name' => $row[0], ]); return [$user, $group]; } }; $import->import('import-users.xlsx'); $this->assertCount(4, DB::getQueryLog()); $this->assertEquals(2, User::count()); $this->assertEquals(2, Group::count()); DB::connection()->disableQueryLog(); } public function test_can_import_models_with_belongs_to_relations() { User::query()->truncate(); Group::query()->truncate(); DB::connection()->enableQueryLog(); $import = new class implements ToModel, PersistRelations { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { $user = new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); $user->group()->associate( new Group([ 'name' => $row[0], ]) ); return $user; } }; $import->import('import-users.xlsx'); $this->assertCount(6, DB::getQueryLog()); $users = User::all(); $users->each(function (User $user) { $this->assertInstanceOf(Group::class, $user->group); $this->assertIsInt($user->group->id); }); $this->assertCount(2, $users); $this->assertEquals(2, Group::count()); DB::connection()->disableQueryLog(); } public function test_can_import_models_with_belongs_to_many_relations() { User::query()->truncate(); Group::query()->truncate(); DB::connection()->enableQueryLog(); $import = new class implements ToModel, PersistRelations { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { $user = new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); $user->setRelation('groups', new Collection([ new Group([ 'name' => $row[0], ]), ])); return $user; } }; $import->import('import-users.xlsx'); $this->assertCount(6, DB::getQueryLog()); $users = User::all(); $users->each(function (User $user) { $this->assertInstanceOf(Group::class, $user->groups->first()); }); $this->assertCount(2, $users); $this->assertEquals(2, Group::count()); DB::connection()->disableQueryLog(); } } ================================================ FILE: tests/Concerns/WithBackgroundColorTest.php ================================================ store('background-styles.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/background-styles.xlsx', 'Xlsx'); $sheet = $spreadsheet->getDefaultStyle(); $this->assertEquals(Fill::FILL_SOLID, $sheet->getFill()->getFillType()); $this->assertEquals('000000', $sheet->getFill()->getStartColor()->getRGB()); } public function test_can_configure_background_color_as_array() { $export = new class implements WithBackgroundColor { use Exportable; public function backgroundColor() { return [ 'fillType' => Fill::FILL_GRADIENT_LINEAR, 'startColor' => ['argb' => Color::COLOR_RED], ]; } }; $export->store('background-styles.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/background-styles.xlsx', 'Xlsx'); $sheet = $spreadsheet->getDefaultStyle(); $this->assertEquals(Fill::FILL_GRADIENT_LINEAR, $sheet->getFill()->getFillType()); $this->assertEquals(Color::COLOR_RED, $sheet->getFill()->getStartColor()->getARGB()); } public function test_can_configure_background_color_with_color_instance() { $export = new class implements WithBackgroundColor { use Exportable; public function backgroundColor() { return new Color(Color::COLOR_BLUE); } }; $export->store('background-styles.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/background-styles.xlsx', 'Xlsx'); $sheet = $spreadsheet->getDefaultStyle(); $this->assertEquals(Fill::FILL_SOLID, $sheet->getFill()->getFillType()); $this->assertEquals(Color::COLOR_BLUE, $sheet->getFill()->getStartColor()->getARGB()); } } ================================================ FILE: tests/Concerns/WithBatchInsertsTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); } public function test_can_import_to_model_in_batches() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithBatchInserts { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return int */ public function batchSize(): int { return 2; } }; $import->import('import-users.xlsx'); $this->assertCount(1, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ]); } public function test_can_import_to_model_in_batches_bigger_file() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithBatchInserts { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function batchSize(): int { return 1000; } }; $import->import('import-batches.xlsx'); $this->assertCount(5000 / $import->batchSize(), DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_multiple_different_types_of_models_in_single_to_model() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithBatchInserts { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { $user = new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); $group = new Group([ 'name' => $row[0], ]); return [$user, $group]; } /** * @return int */ public function batchSize(): int { return 2; } }; $import->import('import-users.xlsx'); // Expected 2 batch queries, 1 for users, 1 for groups $this->assertCount(2, DB::getQueryLog()); $this->assertEquals(2, User::count()); $this->assertEquals(2, Group::count()); DB::connection()->disableQueryLog(); } public function test_has_timestamps_when_imported_in_batches() { $import = new class implements ToModel, WithBatchInserts { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return int */ public function batchSize(): int { return 2; } }; $import->import('import-users.xlsx'); $user = User::first(); $this->assertNotNull($user->created_at); $this->assertNotNull($user->updated_at); } } ================================================ FILE: tests/Concerns/WithCalculatedFormulasTest.php ================================================ called = true; Assert::assertSame('=1+1', $array[0][0]); } }; $import->import('import-formulas.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_array_with_calculated_formulas() { $import = new class implements ToArray, WithCalculatedFormulas { use Importable; public $called = false; /** * @param array $array */ public function array(array $array) { $this->called = true; Assert::assertSame(2, $array[0][0]); } }; $import->import('import-formulas.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_model_with_calculated_formulas() { $import = new class implements ToModel, WithCalculatedFormulas { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function model(array $row) { $this->called = true; Assert::assertSame(2, $row[0]); return null; } }; $import->import('import-formulas.xlsx'); $this->assertTrue($import->called); } public function can_import_with_formulas_and_reference() { $import = new class implements ToModel, WithCalculatedFormulas, WithStartRow { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function model(array $row) { $this->called = true; Assert::assertSame('julien', $row[1]); return null; } public function startRow(): int { return 2; } }; $import->import('import-external-reference.xls'); $this->assertTrue($import->called); } public function test_can_import_to_array_with_calculated_formulas_and_multi_sheet_references() { $import = new class implements WithMultipleSheets, HasReferencesToOtherSheets { use Importable; public $test = 'test1'; public function sheets(): array { return [ new class implements ToArray, HasReferencesToOtherSheets { public $test = 'test2'; public function array(array $array) { Assert::assertEquals([ ['1', '1'], ], $array); } }, new class implements ToArray, WithCalculatedFormulas, HasReferencesToOtherSheets { public $test = 'test2'; public function array(array $array) { Assert::assertEquals([ ['2'], ], $array); } }, ]; } }; $import->import('import-formulas-multiple-sheets.xlsx'); } public function test_can_import_to_array_with_calculated_formulas_and_skips_empty() { $import = new class implements ToArray, WithCalculatedFormulas, SkipsEmptyRows { use Importable; public $called = false; /** * @param array $array */ public function array(array $array) { $this->called = true; Assert::assertSame(2, $array[0][0]); } }; $import->import('import-formulas.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_model_with_calculated_formulas_and_skips_empty() { $import = new class implements ToModel, WithCalculatedFormulas, SkipsEmptyRows { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function model(array $row) { $this->called = true; Assert::assertSame(2, $row[0]); return null; } }; $import->import('import-formulas.xlsx'); $this->assertTrue($import->called); } } ================================================ FILE: tests/Concerns/WithChunkReadingTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); } public function test_can_import_to_model_in_chunks_un() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithChunkReading, WithEvents { use Importable; public $before = 0; public $after = 0; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return int */ public function chunkSize(): int { return 1; } /** * @return array */ public function registerEvents(): array { return [ BeforeImport::class => function (BeforeImport $event) { Assert::assertInstanceOf(Reader::class, $event->reader); $this->before++; }, AfterImport::class => function (AfterImport $event) { Assert::assertInstanceOf(Reader::class, $event->reader); $this->after++; }, ]; } }; $import->import('import-users.xlsx'); $this->assertCount(2, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertEquals(1, $import->before, 'BeforeImport was not called or more than once.'); $this->assertEquals(1, $import->after, 'AfterImport was not called or more than once.'); } public function test_can_import_to_model_in_chunks_and_insert_in_batches() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithChunkReading, WithBatchInserts { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function chunkSize(): int { return 1000; } /** * @return int */ public function batchSize(): int { return 1000; } }; $import->import('import-batches.xlsx'); $this->assertCount(5000 / $import->batchSize(), DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithChunkReading, WithBatchInserts, WithHeadingRow { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row['name'], ]); } /** * @return int */ public function chunkSize(): int { return 1000; } /** * @return int */ public function batchSize(): int { return 1000; } }; $import->import('import-batches-with-heading-row.xlsx'); $this->assertCount(5000 / $import->batchSize(), DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_csv_in_chunks_and_insert_in_batches() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithChunkReading, WithBatchInserts { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function chunkSize(): int { return 1000; } /** * @return int */ public function batchSize(): int { return 1000; } }; $import->import('import-batches.csv'); $this->assertCount(10, DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets() { DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithChunkReading, WithBatchInserts { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function chunkSize(): int { return 1000; } /** * @return int */ public function batchSize(): int { return 1000; } }; $import->import('import-batches-multiple-sheets.xlsx'); $this->assertCount(10, DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_to_array_in_chunks() { $import = new class implements ToArray, WithChunkReading, WithFormatData { use Importable; public $called = 0; /** * @param array $array */ public function array(array $array) { $this->called++; Assert::assertCount(100, $array); } /** * @return int */ public function chunkSize(): int { return 100; } }; $import->import('import-batches.xlsx'); $this->assertEquals(50, $import->called); } public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index() { DB::connection()->enableQueryLog(); $import = new class implements WithMultipleSheets, WithChunkReading { use Importable; /** * @return int */ public function chunkSize(): int { return 1000; } /** * @return array */ public function sheets(): array { return [ new class implements ToModel, WithBatchInserts { /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function batchSize(): int { return 1000; } }, new class implements ToModel, WithBatchInserts { /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function batchSize(): int { return 2000; } }, ]; } }; $import->import('import-batches-multiple-sheets.xlsx'); $this->assertCount(10, DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name() { DB::connection()->enableQueryLog(); $import = new class implements WithMultipleSheets, WithChunkReading { use Importable; /** * @return int */ public function chunkSize(): int { return 1000; } /** * @return array */ public function sheets(): array { return [ 'Worksheet' => new class implements ToModel, WithBatchInserts { /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function batchSize(): int { return 1000; } }, 'Worksheet2' => new class implements ToModel, WithBatchInserts { /** * @param array $row * @return Model|null */ public function model(array $row) { return new Group([ 'name' => $row[0], ]); } /** * @return int */ public function batchSize(): int { return 2000; } }, ]; } }; $import->import('import-batches-multiple-sheets.xlsx'); $this->assertCount(10, DB::getQueryLog()); DB::connection()->disableQueryLog(); } public function test_can_catch_job_failed_in_chunks() { $import = new class implements ToModel, WithChunkReading, WithEvents { use Importable; public $failed = false; /** * @param array $row * @return Model|null */ public function model(array $row) { throw new Exception('Something went wrong in the chunk'); } /** * @return int */ public function chunkSize(): int { return 1; } /** * @return array */ public function registerEvents(): array { return [ ImportFailed::class => function (ImportFailed $event) { Assert::assertInstanceOf(Throwable::class, $event->getException()); Assert::assertEquals('Something went wrong in the chunk', $event->e->getMessage()); $this->failed = true; }, ]; } }; try { $import->import('import-users.xlsx'); } catch (Throwable $e) { $this->assertInstanceOf(Exception::class, $e); $this->assertEquals('Something went wrong in the chunk', $e->getMessage()); } $this->assertTrue($import->failed, 'ImportFailed event was not called.'); } public function test_can_import_to_array_and_format_in_chunks() { config()->set('excel.imports.read_only', false); $import = new class implements ToArray, WithChunkReading, WithFormatData { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertCount(2, $array); Assert::assertCount(1, $array[0]); Assert::assertCount(1, $array[1]); Assert::assertIsString($array[0][0]); Assert::assertIsString($array[1][0]); Assert::assertEquals('01/12/22', $array[0][0]); Assert::assertEquals('2023-02-20', $array[1][0]); } /** * @return int */ public function chunkSize(): int { return 2; } }; $import->import('import-batches-with-date.xlsx'); } public function test_can_import_to_array_in_chunks_without_formatting() { config()->set('excel.imports.read_only', true); $import = new class implements ToArray, WithChunkReading { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertCount(2, $array); Assert::assertCount(1, $array[0]); Assert::assertCount(1, $array[1]); Assert::assertIsInt($array[0][0]); Assert::assertIsInt($array[1][0]); Assert::assertEquals((int) Date::dateTimeToExcel(DateTime::createFromFormat('Y-m-d', '2022-12-01')->setTime(0, 0, 0, 0)), $array[0][0]); Assert::assertEquals((int) Date::dateTimeToExcel(DateTime::createFromFormat('Y-m-d', '2023-02-20')->setTime(0, 0, 0, 0)), $array[1][0]); } /** * @return int */ public function chunkSize(): int { return 2; } }; $import->import('import-batches-with-date.xlsx'); } } ================================================ FILE: tests/Concerns/WithColumnFormattingTest.php ================================================ NumberFormat::FORMAT_DATE_DDMMYYYY, 'B4:B4' => NumberFormat::FORMAT_CURRENCY_EUR, ]; } }; $response = $export->store('with-column-formatting-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-column-formatting-store.xlsx', 'Xlsx'); $legacyPhpSpreadsheet = !InstalledVersions::satisfies(new VersionParser, 'phpoffice/phpspreadsheet', '^1.28'); $expected = [ ['06/03/2018', null], ['07/03/2018', null], ['08/03/2018', null], ['06/12/2021', $legacyPhpSpreadsheet ? '100 €' : '100.00 €'], ]; $this->assertEquals($expected, $actual); } } ================================================ FILE: tests/Concerns/WithColumnLimitTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_import_to_array_with_column_limit() { $import = new class implements ToArray, WithColumnLimit { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'Patrick Brouwers', ], [ 'Taylor Otwell', ], ], $array); } public function endColumn(): string { return 'A'; } }; $import->import('import-users.xlsx'); } public function test_can_import_to_array_with_column_limit_and_skips_empty_rows() { $import = new class implements ToArray, WithColumnLimit, SkipsEmptyRows { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'Test1', 'Test2', null, null, ], [ 'Test3', 'Test4', null, null, ], [ 'Test5', 'Test6', null, null, ], ], $array); } public function endColumn(): string { return 'D'; } }; $import->import('import-empty-rows.xlsx'); } } ================================================ FILE: tests/Concerns/WithColumnWidthsTest.php ================================================ 55, ]; } public function array(): array { return [ ['AA'], ['BB'], ]; } }; $export->store('with-column-widths.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-column-widths.xlsx', 'Xlsx'); $this->assertEquals(55, $spreadsheet->getActiveSheet()->getColumnDimension('A')->getWidth()); } } ================================================ FILE: tests/Concerns/WithConditionalSheetsTest.php ================================================ withFactories(__DIR__ . '/../Data/Stubs/Database/Factories'); } public function test_can_select_which_sheets_will_be_imported() { $import = new class implements WithMultipleSheets { use Importable, WithConditionalSheets; public $sheets = []; public function __construct() { $this->init(); } public function init() { $this->sheets = [ 'Sheet1' => new class implements ToArray { public $called = false; public function array(array $array) { $this->called = true; } }, 'Sheet2' => new class implements ToArray { public $called = false; public function array(array $array) { $this->called = true; } }, ]; } /** * @return array */ public function conditionalSheets(): array { return $this->sheets; } }; $import->onlySheets('Sheet1')->import('import-multiple-sheets.xlsx'); $this->assertTrue($import->sheets['Sheet1']->called); $this->assertFalse($import->sheets['Sheet2']->called); $import->init(); $import->onlySheets('Sheet2')->import('import-multiple-sheets.xlsx'); $this->assertTrue($import->sheets['Sheet2']->called); $this->assertFalse($import->sheets['Sheet1']->called); $import->init(); $import->onlySheets(['Sheet1', 'Sheet2'])->import('import-multiple-sheets.xlsx'); $this->assertTrue($import->sheets['Sheet1']->called); $this->assertTrue($import->sheets['Sheet2']->called); $import->init(); $import->onlySheets('Sheet1', 'Sheet2')->import('import-multiple-sheets.xlsx'); $this->assertTrue($import->sheets['Sheet1']->called); $this->assertTrue($import->sheets['Sheet2']->called); } } ================================================ FILE: tests/Concerns/WithCustomCsvSettingsTest.php ================================================ SUT = $this->app->make(Excel::class); } public function test_can_store_csv_export_with_custom_settings() { $export = new class implements FromCollection, WithCustomCsvSettings { /** * @return Collection */ public function collection() { return collect([ ['A1', 'B1'], ['A2', 'B2'], ]); } /** * @return array */ public function getCsvSettings(): array { return [ 'delimiter' => ';', 'enclosure' => '', 'line_ending' => PHP_EOL, 'use_bom' => true, 'include_separator_line' => true, 'excel_compatibility' => false, 'output_encoding' => '', 'test_auto_detect' => false, ]; } }; $this->SUT->store($export, 'custom-csv.csv'); $contents = file_get_contents(__DIR__ . '/../Data/Disks/Local/custom-csv.csv'); $this->assertStringContains('sep=;', $contents); $this->assertStringContains('A1;B1', $contents); $this->assertStringContains('A2;B2', $contents); } public function test_can_store_csv_export_with_custom_encoding() { $export = new class implements FromCollection, WithCustomCsvSettings { /** * @return Collection */ public function collection() { return collect([ ['A1', '€ŠšŽžŒœŸ'], ['A2', 'åßàèòìù'], ]); } /** * @return array */ public function getCsvSettings(): array { return [ 'delimiter' => ';', 'enclosure' => '', 'line_ending' => PHP_EOL, 'use_bom' => false, 'include_separator_line' => true, 'excel_compatibility' => false, 'output_encoding' => 'ISO-8859-15', ]; } }; $this->SUT->store($export, 'custom-csv-iso.csv'); $contents = file_get_contents(__DIR__ . '/../Data/Disks/Local/custom-csv-iso.csv'); Assert::assertEquals('ISO-8859-15', mb_detect_encoding($contents, 'ISO-8859-15', true)); Assert::assertFalse(mb_detect_encoding($contents, 'UTF-8', true)); $contents = mb_convert_encoding($contents, 'UTF-8', 'ISO-8859-15'); $this->assertStringContains('sep=;', $contents); $this->assertStringContains('A1;€ŠšŽžŒœŸ', $contents); $this->assertStringContains('A2;åßàèòìù', $contents); } public function test_can_read_csv_with_auto_detecting_delimiter_semicolon() { $this->assertEquals([ [ ['a1', 'b1'], ], ], (new HeadingRowImport())->toArray('csv-with-other-delimiter.csv')); } public function test_can_read_csv_with_auto_detecting_delimiter_comma() { $this->assertEquals([ [ ['a1', 'b1'], ], ], (new HeadingRowImport())->toArray('csv-with-comma.csv')); } public function test_can_read_csv_import_with_custom_settings() { $import = new class implements WithCustomCsvSettings, ToArray { /** * @return array */ public function getCsvSettings(): array { return [ 'delimiter' => ';', 'enclosure' => '', 'escape_character' => '\\', 'contiguous' => true, 'input_encoding' => 'UTF-8', ]; } /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ ['A1', 'B1'], ['A2', 'B2'], ], $array); } }; $this->SUT->import($import, 'csv-with-other-delimiter.csv'); } public function test_cannot_read_with_wrong_delimiter() { $import = new class implements WithCustomCsvSettings, ToArray { /** * @return array */ public function getCsvSettings(): array { return [ 'delimiter' => ',', ]; } /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ ['A1;B1'], ['A2;B2'], ], $array); } }; $this->SUT->import($import, 'csv-with-other-delimiter.csv'); } } ================================================ FILE: tests/Concerns/WithCustomQuerySizeTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); $this->withFactories(dirname(__DIR__) . '/Data/Stubs/Database/Factories'); factory(Group::class)->times(5)->create()->each(function ($group) { $group->users()->attach(factory(User::class)->times(rand(1, 3))->create()); }); config()->set('excel.exports.chunk_size', 2); } public function test_can_export_with_custom_count() { $export = new FromQueryWithCustomQuerySize(); $export->queue('export-from-query-with-count.xlsx', null, 'Xlsx')->chain([ new AfterQueueExportJob(dirname(__DIR__) . '/Data/Disks/Local/export-from-query-with-count.xlsx'), ]); $actual = $this->readAsArray(dirname(__DIR__) . '/Data/Disks/Local/export-from-query-with-count.xlsx', 'Xlsx'); $this->assertCount(Group::count(), $actual); } } ================================================ FILE: tests/Concerns/WithCustomStartCellTest.php ================================================ SUT = $this->app->make(Excel::class); } public function test_can_store_collection_with_custom_start_cell() { $export = new class implements FromCollection, WithCustomStartCell { /** * @return Collection */ public function collection() { return collect([ ['A1', 'B1'], ['A2', 'B2'], ]); } /** * @return string */ public function startCell(): string { return 'B2'; } }; $this->SUT->store($export, 'custom-start-cell.csv'); $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/custom-start-cell.csv', 'Csv'); $this->assertEquals([ [null, null, null], [null, 'A1', 'B1'], [null, 'A2', 'B2'], ], $contents); } } ================================================ FILE: tests/Concerns/WithCustomValueBinderTest.php ================================================ setValueExplicit( (float) str_replace('%', '', $value) / 100, DataType::TYPE_NUMERIC ); $cell ->getWorksheet() ->getStyle($cell->getCoordinate()) ->getNumberFormat() ->setFormatCode(NumberFormat::FORMAT_PERCENTAGE_00); return true; } // Handle Carbon dates if ($value instanceof Carbon) { $cell->setValueExplicit( Date::dateTimeToExcel($value), DataType::TYPE_NUMERIC ); $cell->getWorksheet() ->getStyle($cell->getCoordinate()) ->getNumberFormat() ->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME); return true; } return parent::bindValue($cell, $value); } }; $export->store('custom-value-binder-export.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/custom-value-binder-export.xlsx', 'Xlsx'); $sheet = $spreadsheet->getActiveSheet(); // Check if the cell has the Excel date $this->assertSame(Date::dateTimeToExcel(Carbon::now()), $sheet->getCell('A1')->getValue()); // Check if formatted as datetime $this->assertEquals(NumberFormat::FORMAT_DATE_DATETIME, $sheet->getCell('A1')->getStyle()->getNumberFormat()->getFormatCode()); // Check if the cell has the converted percentage $this->assertSame(0.1, $sheet->getCell('B1')->getValue()); // Check if formatted as percentage $this->assertEquals(NumberFormat::FORMAT_PERCENTAGE_00, $sheet->getCell('B1')->getStyle()->getNumberFormat()->getFormatCode()); } public function test_can_set_a_value_binder_on_import() { $import = new class extends DefaultValueBinder implements WithCustomValueBinder, ToArray { /** * {@inheritdoc} */ public function bindValue(Cell $cell, $value) { if ($cell->getCoordinate() === 'B2') { $cell->setValueExplicit($value, DataType::TYPE_STRING); return true; } if ($cell->getRow() === 3) { $date = Carbon::instance(Date::excelToDateTimeObject($value)); $cell->setValueExplicit($date->toDateTimeString(), DataType::TYPE_STRING); return true; } return parent::bindValue($cell, $value); } /** * @param array $array */ public function array(array $array) { Assert::assertSame([ [ 'col1', 'col2', ], [ 1, '2', // Forced to be a string ], [ '2018-08-06 18:31:46', // Convert Excel datetime to datetime strings '2018-08-07 00:00:00', // Convert Excel date to datetime strings ], ], $array); } }; $this->app->make(Excel::class)->import($import, 'value-binder-import.xlsx'); } } ================================================ FILE: tests/Concerns/WithDefaultStylesTest.php ================================================ [ 'fillType' => Fill::FILL_SOLID, 'startColor' => ['argb' => 'fff2f2f2'], ], ]; } public function array(): array { return [ ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ]; } }; $export->store('with-default-styles.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-default-styles.xlsx', 'Xlsx'); $sheet = $spreadsheet->getDefaultStyle(); $this->assertEquals(Fill::FILL_SOLID, $sheet->getFill()->getFillType()); $this->assertEquals('fff2f2f2', $sheet->getFill()->getStartColor()->getARGB()); } } ================================================ FILE: tests/Concerns/WithEventsTest.php ================================================ beforeExport = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeExport::class, $event); $this->assertInstanceOf(Writer::class, $event->getWriter()); $eventsTriggered++; }; $event->beforeWriting = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeWriting::class, $event); $this->assertInstanceOf(Writer::class, $event->getWriter()); $eventsTriggered++; }; $event->beforeSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->getSheet()); $eventsTriggered++; }; $event->afterSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(AfterSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->getSheet()); $eventsTriggered++; }; $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx')); $this->assertEquals(4, $eventsTriggered); } public function test_import_events_get_called() { $import = new ImportWithEvents(); $eventsTriggered = 0; $import->beforeImport = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeImport::class, $event); $this->assertInstanceOf(Reader::class, $event->getReader()); $eventsTriggered++; }; $import->afterImport = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(AfterImport::class, $event); $this->assertInstanceOf(Reader::class, $event->getReader()); $eventsTriggered++; }; $import->beforeSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(BeforeSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->getSheet()); $eventsTriggered++; }; $import->afterSheet = function ($event) use (&$eventsTriggered) { $this->assertInstanceOf(AfterSheet::class, $event); $this->assertInstanceOf(Sheet::class, $event->getSheet()); $eventsTriggered++; }; $import->import('import.xlsx'); $this->assertEquals(4, $eventsTriggered); } public function test_import_chunked_events_get_called() { $import = new ImportWithEventsChunksAndBatches(); $beforeImport = 0; $afterImport = 0; $beforeSheet = 0; $afterSheet = 0; $afterBatch = 0; $afterChunk = 0; $import->beforeImport = function (BeforeImport $event) use (&$beforeImport) { $this->assertInstanceOf(Reader::class, $event->getReader()); // Ensure event is fired only once $this->assertEquals(0, $beforeImport, 'Before import called twice'); $beforeImport++; }; $import->afterImport = function (AfterImport $event) use (&$afterImport) { $this->assertInstanceOf(Reader::class, $event->getReader()); $this->assertEquals(0, $afterImport, 'After import called twice'); $afterImport++; }; $import->beforeSheet = function (BeforeSheet $event) use (&$beforeSheet) { $this->assertInstanceOf(Sheet::class, $event->getSheet()); $beforeSheet++; }; $import->afterSheet = function (AfterSheet $event) use (&$afterSheet) { $this->assertInstanceOf(Sheet::class, $event->getSheet()); $afterSheet++; }; $import->afterBatch = function (AfterBatch $event) use ($import, &$afterBatch) { $this->assertEquals( $import->batchSize(), $event->getBatchSize(), 'Wrong Batch size' ); $this->assertEquals( $afterBatch * $import->batchSize() + 1, $event->getStartRow(), 'Wrong batch start row'); $afterBatch++; }; $import->afterChunk = function (AfterChunk $event) use ($import, &$afterChunk) { $this->assertEquals( $event->getStartRow(), $afterChunk * $import->chunkSize() + 1, 'Wrong chunk start row'); $afterChunk++; }; $import->import('import-batches.xlsx'); $this->assertEquals(10, $afterSheet); $this->assertEquals(10, $beforeSheet); $this->assertEquals(50, $afterBatch); $this->assertEquals(10, $afterChunk); } public function test_can_have_invokable_class_as_listener() { $event = new ExportWithEvents(); $event->beforeExport = new BeforeExportListener(function ($event) { $this->assertInstanceOf(BeforeExport::class, $event); $this->assertInstanceOf(Writer::class, $event->getWriter()); }); $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx')); } public function test_can_have_global_event_listeners() { $event = new class { use Exportable; }; $beforeExport = false; Writer::listen(BeforeExport::class, function () use (&$beforeExport) { $beforeExport = true; }); $beforeWriting = false; Writer::listen(BeforeWriting::class, function () use (&$beforeWriting) { $beforeWriting = true; }); $beforeSheet = false; Sheet::listen(BeforeSheet::class, function () use (&$beforeSheet) { $beforeSheet = true; }); $afterSheet = false; Sheet::listen(AfterSheet::class, function () use (&$afterSheet) { $afterSheet = true; }); $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx')); $this->assertTrue($beforeExport, 'Before export event not triggered'); $this->assertTrue($beforeWriting, 'Before writing event not triggered'); $this->assertTrue($beforeSheet, 'Before sheet event not triggered'); $this->assertTrue($afterSheet, 'After sheet event not triggered'); } public function test_can_have_custom_concern_handlers() { // Add a custom concern handler for the given concern. Excel::extend(CustomConcern::class, function (CustomConcern $exportable, Writer $writer) { $writer->getSheetByIndex(0)->append( $exportable->custom() ); }); $exportWithConcern = new class implements CustomConcern { use Exportable; public function custom() { return [ ['a', 'b'], ]; } }; $exportWithConcern->store('with-custom-concern.xlsx'); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-custom-concern.xlsx', 'Xlsx'); $this->assertEquals([ ['a', 'b'], ], $actual); $exportWithoutConcern = new class { use Exportable; }; $exportWithoutConcern->store('without-custom-concern.xlsx'); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/without-custom-concern.xlsx', 'Xlsx'); $this->assertEquals([[null]], $actual); } public function test_can_have_custom_sheet_concern_handlers() { // Add a custom concern handler for the given concern. Excel::extend(CustomSheetConcern::class, function (CustomSheetConcern $exportable, Sheet $sheet) { $sheet->append( $exportable->custom() ); }, AfterSheet::class); $exportWithConcern = new class implements CustomSheetConcern { use Exportable; public function custom() { return [ ['c', 'd'], ]; } }; $exportWithConcern->store('with-custom-concern.xlsx'); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-custom-concern.xlsx', 'Xlsx'); $this->assertEquals([ ['c', 'd'], ], $actual); $exportWithoutConcern = new class { use Exportable; }; $exportWithoutConcern->store('without-custom-concern.xlsx'); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/without-custom-concern.xlsx', 'Xlsx'); $this->assertEquals([[null]], $actual); } public function test_export_chunked_events_get_called() { $this->loadLaravelMigrations(['--database' => 'testing']); User::query()->truncate(); User::query()->create([ 'name' => $this->faker->name, 'email' => $this->faker->unique()->safeEmail, 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret 'remember_token' => Str::random(10), ]); User::query()->create([ 'name' => $this->faker->name, 'email' => $this->faker->unique()->safeEmail, 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret 'remember_token' => Str::random(10), ]); $export = new ExportWithEventsChunks(); $export->queue('filename.xlsx'); // Chunk size is 1, so we expect 2 chunks to be executed with a total of 2 users $this->assertEquals(2, ExportWithEventsChunks::$calledEvent); } } ================================================ FILE: tests/Concerns/WithFormatDataTest.php ================================================ called = true; Assert::assertSame(44328, $array[0][0]); } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_array_with_format_data() { config()->set('excel.imports.read_only', false); $import = new class implements ToArray, WithFormatData { use Importable; public $called = false; /** * @param array $array */ public function array(array $array) { $this->called = true; Assert::assertSame('5/12/2021', $array[0][0]); } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_array_with_format_data_and_skips_empty_rows() { config()->set('excel.imports.read_only', false); $import = new class implements ToArray, WithFormatData, SkipsEmptyRows { use Importable; public $called = false; /** * @param array $array */ public function array(array $array) { $this->called = true; Assert::assertSame('5/12/2021', $array[0][0]); } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } public function test_by_default_import_to_collection() { $import = new class implements ToCollection { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function collection(collection $collection) { $this->called = true; Assert::assertSame(44328, $collection[0][0]); return null; } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_collection_with_format_data() { config()->set('excel.imports.read_only', false); $import = new class implements ToCollection, WithFormatData { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function collection(collection $collection) { $this->called = true; Assert::assertSame('5/12/2021', $collection[0][0]); return null; } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } public function test_by_default_import_to_model() { $import = new class implements ToModel { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function model(array $row) { $this->called = true; Assert::assertSame(44328, $row[0]); return null; } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } public function test_can_import_to_model_with_format_data() { config()->set('excel.imports.read_only', false); $import = new class implements ToModel, WithFormatData { use Importable; public $called = false; /** * @param array $row * @return Model|null */ public function model(array $row) { $this->called = true; Assert::assertSame('5/12/2021', $row[0]); return null; } }; $import->import('import-format-data.xlsx'); $this->assertTrue($import->called); } } ================================================ FILE: tests/Concerns/WithGroupedHeadingRowTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); } public function test_can_import_to_array_with_grouped_headers() { $import = new class implements ToArray, WithGroupedHeadingRow { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'options' => [ 'laravel', 'excel', ], ], ], $array); } }; $import->import('import-users-with-grouped-headers.xlsx'); } public function test_can_import_oneachrow_with_grouped_headers() { $import = new class implements OnEachRow, WithGroupedHeadingRow { use Importable; /** * @param \Maatwebsite\Excel\Row $row * @return void */ public function onRow(Row $row) { Assert::assertEquals( [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'options' => [ 'laravel', 'excel', ], ], $row->toArray()); } }; $import->import('import-users-with-grouped-headers.xlsx'); } public function test_can_import_to_collection_with_grouped_headers() { $import = new class implements ToCollection, WithGroupedHeadingRow { use Importable; public $called = false; /** * @param Collection $collection */ public function collection(Collection $collection) { $this->called = true; Assert::assertEquals([ [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'options' => [ 'laravel', 'excel', ], ], ], $collection->toArray()); } }; $import->import('import-users-with-grouped-headers.xlsx'); $this->assertTrue($import->called); } public function test_can_import_each_row_to_model_with_grouped_headers() { $import = new class implements ToModel, WithGroupedHeadingRow { use Importable; /** * @param array $row * @return Model */ public function model(array $row): Model { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', 'options' => $row['options'], ]); } }; $import->import('import-users-with-grouped-headers.xlsx'); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'options' => '["laravel","excel"]', ]); } } ================================================ FILE: tests/Concerns/WithHeadingRowTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_import_each_row_to_model_with_heading_row() { $import = new class implements ToModel, WithHeadingRow { use Importable; /** * @param array $row * @return Model */ public function model(array $row): Model { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', ]); } }; $import->import('import-users-with-headings.xlsx'); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ]); } public function test_can_import_each_row_to_model_with_different_heading_row() { $import = new class implements ToModel, WithHeadingRow { use Importable; /** * @param array $row * @return Model */ public function model(array $row): Model { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', ]); } /** * @return int */ public function headingRow(): int { return 4; } }; $import->import('import-users-with-different-heading-row.xlsx'); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ]); } public function test_can_import_to_array_with_heading_row() { $import = new class implements ToArray, WithHeadingRow { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ], [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ], ], $array); } }; $import->import('import-users-with-headings.xlsx'); } public function test_can_import_empty_rows_with_header() { $import = new class() implements ToArray, WithHeadingRow { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEmpty($array); } }; $import->import('import-empty-users-with-headings.xlsx'); } public function test_can_import_empty_models_with_header() { $import = new class() implements ToModel, WithHeadingRow { use Importable; /** * @param array $row * @return Model */ public function model(array $row): Model { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', ]); } }; $import->import('import-empty-users-with-headings.xlsx'); $this->assertEmpty(User::all()); } public function test_can_cast_empty_headers_to_indexed_int() { $import = new class() implements ToCollection, WithHeadingRow { use Importable; public $called = false; public function collection(Collection $collection) { $this->called = true; Assert::assertEquals([ 0 => 0, 1 => 'email', 2 => 'status', 3 => 3, ], $collection->first()->keys()->toArray()); } }; $import->import('import-users-with-mixed-headings.xlsx'); $this->assertTrue($import->called); } } ================================================ FILE: tests/Concerns/WithHeadingsTest.php ================================================ store('with-heading-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-heading-store.xlsx', 'Xlsx'); $expected = [ ['A', 'B', 'C'], ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ]; $this->assertEquals($expected, $actual); } public function test_can_export_from_collection_with_multiple_heading_rows() { $export = new class implements FromCollection, WithHeadings { use Exportable; /** * @return Collection */ public function collection() { return collect([ ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ]); } /** * @return array */ public function headings(): array { return [ ['A', 'B', 'C'], ['Aa', 'Bb', 'Cc'], ]; } }; $response = $export->store('with-heading-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-heading-store.xlsx', 'Xlsx'); $expected = [ ['A', 'B', 'C'], ['Aa', 'Bb', 'Cc'], ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ]; $this->assertEquals($expected, $actual); } public function test_can_export_from_collection_with_heading_row_with_custom_start_cell() { $export = new class implements FromCollection, WithHeadings, WithCustomStartCell { use Exportable; /** * @return Collection */ public function collection() { return collect([ ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ]); } /** * @return array */ public function headings(): array { return ['A', 'B', 'C']; } /** * @return string */ public function startCell(): string { return 'B2'; } }; $response = $export->store('with-heading-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-heading-store.xlsx', 'Xlsx'); $expected = [ [null, null, null, null], [null, 'A', 'B', 'C'], [null, 'A1', 'B1', 'C1'], [null, 'A2', 'B2', 'C2'], ]; $this->assertEquals($expected, $actual); } } ================================================ FILE: tests/Concerns/WithLimitTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_import_a_limited_section_of_rows_to_model_with_different_start_row() { $import = new class implements ToModel, WithStartRow, WithLimit { use Importable; /** * @param array $row * @return Model */ public function model(array $row): Model { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return int */ public function startRow(): int { return 5; } /** * @return int */ public function limit(): int { return 1; } }; $import->import('import-users-with-different-heading-row.xlsx'); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); $this->assertDatabaseMissing('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ]); } public function test_can_import_to_array_with_limit() { $import = new class implements ToArray, WithLimit { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'Patrick Brouwers', 'patrick@maatwebsite.nl', ], ], $array); } /** * @return int */ public function limit(): int { return 1; } }; $import->import('import-users.xlsx'); } public function test_can_import_single_with_heading_row() { $import = new class implements ToArray, WithLimit, WithHeadingRow { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ], ], $array); } /** * @return int */ public function limit(): int { return 1; } }; $import->import('import-users-with-headings.xlsx'); } public function test_can_import_multiple_with_heading_row() { $import = new class implements ToArray, WithLimit, WithHeadingRow { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ], [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ], ], $array); } /** * @return int */ public function limit(): int { return 2; } }; $import->import('import-users-with-headings.xlsx'); } public function test_can_set_limit_bigger_than_row_size() { $import = new class implements ToArray, WithLimit { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertCount(2, $array); } /** * @return int */ public function limit(): int { return 10; } }; $import->import('import-users.xlsx'); } } ================================================ FILE: tests/Concerns/WithMappedCellsTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_import_with_references_to_cells() { $import = new class implements WithMappedCells, ToArray { use Importable; /** * @return array */ public function mapping(): array { return [ 'name' => 'B1', 'email' => 'B2', ]; } /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ], $array); } }; $import->import('mapped-import.xlsx'); } public function test_can_import_with_nested_references_to_cells() { $import = new class implements WithMappedCells, ToArray { use Importable; /** * @return array */ public function mapping(): array { return [ [ 'name' => 'B1', 'email' => 'B2', ], [ 'name' => 'D1', 'email' => 'D2', ], ]; } /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ], [ 'name' => 'Typingbeaver', 'email' => 'typingbeaver@mailbox.org', ], ], $array); } }; $import->import('mapped-import.xlsx'); } public function test_can_import_with_references_to_cells_to_model() { $import = new class implements WithMappedCells, ToModel { use Importable; /** * @return array */ public function mapping(): array { return [ 'name' => 'B1', 'email' => 'B2', ]; } /** * @param array $array * @return User */ public function model(array $array) { Assert::assertEquals([ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ], $array); $array['password'] = Str::random(); return new User($array); } }; $import->import('mapped-import.xlsx'); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); } } ================================================ FILE: tests/Concerns/WithMappingTest.php ================================================ store('with-mapping-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-mapping-store.xlsx', 'Xlsx'); $expected = [ [ 'mapped-A1', 'mapped-B1', 'mapped-C1', ], [ 'mapped-A2', 'mapped-B2', 'mapped-C2', ], ]; $this->assertEquals($expected, $actual); } public function test_can_return_multiple_rows_in_map() { $export = new class implements FromArray, WithMapping { use Exportable; /** * @return array */ public function array(): array { return [ ['id' => 1], ['id' => 2], ['id' => 3], ]; } /** * @param mixed $row * @return array */ public function map($row): array { return [ [$row['id']], [$row['id']], ]; } }; $response = $export->store('with-mapping-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-mapping-store.xlsx', 'Xlsx'); $this->assertCount(6, $actual); } public function test_json_array_columns_shouldnt_be_detected_as_multiple_rows() { $export = new class implements FromArray { use Exportable; /** * @return array */ public function array(): array { return [ ['id' => 1, 'json' => ['other_id' => 1]], ['id' => 2, 'json' => ['other_id' => 2]], ['id' => 3, 'json' => ['other_id' => 3]], ]; } }; $response = $export->store('with-mapping-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-mapping-store.xlsx', 'Xlsx'); $this->assertCount(3, $actual); $this->assertEquals([ [1, \json_encode(['other_id' => 1])], [2, \json_encode(['other_id' => 2])], [3, \json_encode(['other_id' => 3])], ], $actual); } } ================================================ FILE: tests/Concerns/WithMultipleSheetsTest.php ================================================ withFactories(__DIR__ . '/../Data/Stubs/Database/Factories'); } public function test_can_export_with_multiple_sheets_using_collections() { $export = new class implements WithMultipleSheets { use Exportable; /** * @return SheetWith100Rows[] */ public function sheets(): array { return [ new SheetWith100Rows('A'), new SheetWith100Rows('B'), new SheetWith100Rows('C'), ]; } }; $export->store('from-view.xlsx'); $this->assertCount(100, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 0)); $this->assertCount(100, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 1)); $this->assertCount(100, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 2)); } public function test_can_export_multiple_sheets_from_view() { /** @var Collection|User[] $users */ $users = factory(User::class)->times(300)->make(); $export = new class($users) implements WithMultipleSheets { use Exportable; /** * @var Collection */ protected $users; /** * @param Collection $users */ public function __construct(Collection $users) { $this->users = $users; } /** * @return SheetForUsersFromView[] */ public function sheets(): array { return [ new SheetForUsersFromView($this->users->forPage(1, 100)), new SheetForUsersFromView($this->users->forPage(2, 100)), new SheetForUsersFromView($this->users->forPage(3, 100)), ]; } }; $export->store('from-view.xlsx'); $this->assertCount(101, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 0)); $this->assertCount(101, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 1)); $this->assertCount(101, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 2)); } public function test_unknown_sheet_index_will_throw_sheet_not_found_exception() { $this->expectException(\Maatwebsite\Excel\Exceptions\SheetNotFoundException::class); $this->expectExceptionMessage('Your requested sheet index: 9999 is out of bounds. The actual number of sheets is 2.'); $import = new class implements WithMultipleSheets { use Importable; public function sheets(): array { return [ 9999 => new class { }, ]; } }; $import->import('import-multiple-sheets.xlsx'); } public function test_unknown_sheet_name_will_throw_sheet_not_found_exception() { $this->expectException(\Maatwebsite\Excel\Exceptions\SheetNotFoundException::class); $this->expectExceptionMessage('Your requested sheet name [Some Random Sheet Name] is out of bounds.'); $import = new class implements WithMultipleSheets { use Importable; public function sheets(): array { return [ 'Some Random Sheet Name' => new class { }, ]; } }; $import->import('import-multiple-sheets.xlsx'); } public function test_unknown_sheet_name_can_be_ignored() { $import = new class implements WithMultipleSheets, SkipsUnknownSheets { use Importable; public $unknown; public function sheets(): array { return [ 'Some Random Sheet Name' => new class { }, ]; } /** * @param string|int $sheetName */ public function onUnknownSheet($sheetName) { $this->unknown = $sheetName; } }; $import->import('import-multiple-sheets.xlsx'); $this->assertEquals('Some Random Sheet Name', $import->unknown); } public function test_unknown_sheet_indices_can_be_ignored_per_name() { $import = new class implements WithMultipleSheets { use Importable; public function sheets(): array { return [ 'Some Random Sheet Name' => new class implements SkipsUnknownSheets { /** * @param string|int $sheetName */ public function onUnknownSheet($sheetName) { Assert::assertEquals('Some Random Sheet Name', $sheetName); } }, ]; } }; $import->import('import-multiple-sheets.xlsx'); } public function test_unknown_sheet_indices_can_be_ignored() { $import = new class implements WithMultipleSheets, SkipsUnknownSheets { use Importable; public $unknown; public function sheets(): array { return [ 99999 => new class { }, ]; } /** * @param string|int $sheetName */ public function onUnknownSheet($sheetName) { $this->unknown = $sheetName; } }; $import->import('import-multiple-sheets.xlsx'); $this->assertEquals(99999, $import->unknown); } public function test_unknown_sheet_indices_can_be_ignored_per_sheet() { $import = new class implements WithMultipleSheets { use Importable; public function sheets(): array { return [ 99999 => new class implements SkipsUnknownSheets { /** * @param string|int $sheetName */ public function onUnknownSheet($sheetName) { Assert::assertEquals(99999, $sheetName); } }, ]; } }; $import->import('import-multiple-sheets.xlsx'); } public function test_can_import_multiple_sheets() { $import = new class implements WithMultipleSheets { use Importable; public function sheets(): array { return [ new class implements ToArray { public function array(array $array) { Assert::assertEquals([ ['1.A1', '1.B1'], ['1.A2', '1.B2'], ], $array); } }, new class implements ToArray { public function array(array $array) { Assert::assertEquals([ ['2.A1', '2.B1'], ['2.A2', '2.B2'], ], $array); } }, ]; } }; $import->import('import-multiple-sheets.xlsx'); } public function test_can_import_multiple_sheets_by_sheet_name() { $import = new class implements WithMultipleSheets { use Importable; public function sheets(): array { return [ 'Sheet2' => new class implements ToArray { public function array(array $array) { Assert::assertEquals([ ['2.A1', '2.B1'], ['2.A2', '2.B2'], ], $array); } }, 'Sheet1' => new class implements ToArray { public function array(array $array) { Assert::assertEquals([ ['1.A1', '1.B1'], ['1.A2', '1.B2'], ], $array); } }, ]; } }; $import->import('import-multiple-sheets.xlsx'); } public function test_can_import_multiple_sheets_by_sheet_index_and_name() { $import = new class implements WithMultipleSheets { use Importable; public $sheets = []; public function __construct() { $this->sheets = [ 0 => new class implements ToArray { public $called = false; public function array(array $array) { $this->called = true; Assert::assertEquals([ ['1.A1', '1.B1'], ['1.A2', '1.B2'], ], $array); } }, 'Sheet2' => new class implements ToArray { public $called = false; public function array(array $array) { $this->called = true; Assert::assertEquals([ ['2.A1', '2.B1'], ['2.A2', '2.B2'], ], $array); } }, ]; } public function sheets(): array { return $this->sheets; } }; $import->import('import-multiple-sheets.xlsx'); foreach ($import->sheets as $sheet) { $this->assertTrue($sheet->called); } } public function test_can_import_multiple_sheets_by_sheet_name_and_index() { $import = new class implements WithMultipleSheets { use Importable; public $sheets = []; public function __construct() { $this->sheets = [ 'Sheet1' => new class implements ToArray { public $called = false; public function array(array $array) { $this->called = true; Assert::assertEquals([ ['1.A1', '1.B1'], ['1.A2', '1.B2'], ], $array); } }, 1 => new class implements ToArray { public $called = false; public function array(array $array) { $this->called = true; Assert::assertEquals([ ['2.A1', '2.B1'], ['2.A2', '2.B2'], ], $array); } }, ]; } public function sheets(): array { return $this->sheets; } }; $import->import('import-multiple-sheets.xlsx'); foreach ($import->sheets as $sheet) { $this->assertTrue($sheet->called); } } } ================================================ FILE: tests/Concerns/WithPropertiesTest.php ================================================ 'A', 'lastModifiedBy' => 'B', 'title' => 'C', 'description' => 'D', 'subject' => 'E', 'keywords' => 'F', 'category' => 'G', 'manager' => 'H', 'company' => 'I', ]; } }; $export->store('with-properties.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-properties.xlsx', 'Xlsx'); $props = $spreadsheet->getProperties(); $this->assertEquals('A', $props->getCreator()); $this->assertEquals('B', $props->getLastModifiedBy()); $this->assertEquals('C', $props->getTitle()); $this->assertEquals('D', $props->getDescription()); $this->assertEquals('E', $props->getSubject()); $this->assertEquals('F', $props->getKeywords()); $this->assertEquals('G', $props->getCategory()); $this->assertEquals('H', $props->getManager()); $this->assertEquals('I', $props->getCompany()); } public function test_it_merges_with_default_properties() { config()->set('excel.exports.properties.title', 'Default Title'); config()->set('excel.exports.properties.description', 'Default Description'); $export = new class implements WithProperties { use Exportable; public function properties(): array { return [ 'description' => 'Custom Description', ]; } }; $export->store('with-properties.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-properties.xlsx', 'Xlsx'); $props = $spreadsheet->getProperties(); $this->assertEquals('Default Title', $props->getTitle()); $this->assertEquals('Custom Description', $props->getDescription()); } public function test_it_ignores_empty_properties() { $export = new class implements WithProperties { use Exportable; public function properties(): array { return [ 'description' => '', ]; } }; $export->store('with-properties.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-properties.xlsx', 'Xlsx'); $props = $spreadsheet->getProperties(); $this->assertSame('Unknown Creator', $props->getCreator()); $this->assertSame('Untitled Spreadsheet', $props->getTitle()); $this->assertSame('', $props->getDescription()); } } ================================================ FILE: tests/Concerns/WithReadFilterTest.php ================================================ toArray('import-users.xlsx'); } } ================================================ FILE: tests/Concerns/WithSkipDuplicatesTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_skip_duplicate_models_in_batches() { User::create([ 'name' => 'Funny Banana', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithBatchInserts, WithSkipDuplicates { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return string|array */ public function uniqueBy() { return 'email'; } /** * @return int */ public function batchSize(): int { return 2; } }; $import->import('import-users.xlsx'); $this->assertCount(1, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Funny Banana', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', 'password' => 'secret', ]); $this->assertEquals(2, User::count()); } public function test_can_skip_duplicate_models_in_rows() { User::create([ 'name' => 'Funny Potato', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithSkipDuplicates { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return string|array */ public function uniqueBy() { return 'email'; } }; $import->import('import-users.xlsx'); $this->assertCount(2, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Funny Potato', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', 'password' => 'secret', ]); $this->assertEquals(2, User::count()); } } ================================================ FILE: tests/Concerns/WithStartRowTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); } public function test_can_import_each_row_to_model_with_different_start_row() { $import = new class implements ToModel, WithStartRow { use Importable; /** * @param array $row * @return Model */ public function model(array $row): Model { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return int */ public function startRow(): int { return 5; } }; $import->import('import-users-with-different-heading-row.xlsx'); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', ]); } public function test_can_import_to_array_with_start_row() { $import = new class implements ToArray, WithStartRow { use Importable; /** * @param array $array */ public function array(array $array) { Assert::assertEquals([ [ 'Patrick Brouwers', 'patrick@maatwebsite.nl', ], [ 'Taylor Otwell', 'taylor@laravel.com', ], ], $array); } /** * @return int */ public function startRow(): int { return 5; } }; $import->import('import-users-with-different-heading-row.xlsx'); } } ================================================ FILE: tests/Concerns/WithStrictNullComparisonTest.php ================================================ store('with-strict-null-comparison-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-strict-null-comparison-store.xlsx', 'Xlsx'); $expected = [ ['string', 0.0, 0.0, 0.0, 'string'], ['string', 0.0, 0.0, 0.0, 'string'], ]; $this->assertEquals($expected, $actual); } public function test_exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison() { $export = new class implements FromCollection, WithHeadings { use Exportable; /** * @return Collection */ public function collection() { return collect([ ['string', 0, 0.0, 'string'], ]); } /** * @return array */ public function headings(): array { return ['string', 0, 0.0, 'string']; } }; $response = $export->store('without-strict-null-comparison-store.xlsx'); $this->assertTrue($response); $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/without-strict-null-comparison-store.xlsx', 'Xlsx'); $expected = [ ['string', null, null, 'string'], ['string', null, null, 'string'], ]; $this->assertEquals($expected, $actual); } public function test_exports_trailing_empty_cells() { $export = new class implements FromCollection, WithStrictNullComparison { use Exportable; /** * @return Collection */ public function collection() { return collect([ ['a1', '', '', 'd1', ''], ['a2', '', '', 'd2', ''], ]); } }; $response = $export->store('empty-cells.csv'); $this->assertTrue($response); $file = __DIR__ . '/../Data/Disks/Local/empty-cells.csv'; $actual = $this->readAsArray($file, 'Csv'); $expected = [ ['a1', null, null, 'd1'], ['a2', null, null, 'd2'], ]; $this->assertEquals($expected, $actual); $contents = file_get_contents($file); $this->assertStringContains('"a1","","","d1",""', $contents); $this->assertStringContains('"a2","","","d2",""', $contents); } public function test_exports_trailing_empty_cells_by_setting_config_strict_null_comparison() { config()->set('excel.exports.strict_null_comparison', false); $export = new class implements FromCollection { use Exportable; /** * @return Collection */ public function collection() { return collect([ ['a1', '', '', 'd1', ''], ['a2', '', '', 'd2', ''], ]); } }; $file = __DIR__ . '/../Data/Disks/Local/empty-cells-config.csv'; $export->store('empty-cells-config.csv'); $contents = file_get_contents($file); $this->assertStringContains('"a1","","","d1"', $contents); config()->set('excel.exports.strict_null_comparison', true); $export->store('empty-cells-config.csv'); $contents = file_get_contents($file); $this->assertStringContains('"a1","","","d1",""', $contents); } } ================================================ FILE: tests/Concerns/WithStylesTest.php ================================================ ['font' => ['italic' => true]], 'B2' => ['font' => ['bold' => true]], 'C' => ['font' => ['size' => 16]], ]; } public function array(): array { return [ ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ]; } }; $export->store('with-styles.xlsx'); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-styles.xlsx', 'Xlsx'); $sheet = $spreadsheet->getActiveSheet(); $this->assertTrue($sheet->getStyle('A1')->getFont()->getItalic()); $this->assertTrue($sheet->getStyle('B1')->getFont()->getItalic()); $this->assertTrue($sheet->getStyle('B2')->getFont()->getBold()); $this->assertFalse($sheet->getStyle('A2')->getFont()->getBold()); $this->assertEquals(16, $sheet->getStyle('C2')->getFont()->getSize()); } } ================================================ FILE: tests/Concerns/WithTitleTest.php ================================================ store('with-title-store.xlsx'); $this->assertTrue($response); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-title-store.xlsx', 'Xlsx'); $this->assertEquals('given-title', $spreadsheet->getProperties()->getTitle()); $this->assertEquals('given-title', $spreadsheet->getActiveSheet()->getTitle()); } public function test_can_export_sheet_title_when_longer_than_max_length() { $export = new class implements WithTitle, WithMultipleSheets { use Exportable; /** * @return string */ public function title(): string { return '12/3456789123/45678912345/678912345/6789'; } public function sheets(): array { return [$this]; } }; $response = $export->store('with-title-store.xlsx'); $this->assertTrue($response); $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-title-store.xlsx', 'Xlsx'); $this->assertEquals('12/3456789123/45678912345/678912345/6789', $spreadsheet->getProperties()->getTitle()); $this->assertEquals('1234567891234567891234567891234', $spreadsheet->getActiveSheet()->getTitle()); } } ================================================ FILE: tests/Concerns/WithUpsertsTest.php ================================================ markTestSkipped('The upsert feature is available on Laravel 8.10+'); } parent::setUp(); $this->loadLaravelMigrations(['--database' => 'testing']); } public function test_can_upsert_models_in_batches() { User::create([ 'name' => 'Funny Banana', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithBatchInserts, WithUpserts { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return string|array */ public function uniqueBy() { return 'email'; } /** * @return int */ public function batchSize(): int { return 2; } }; $import->import('import-users.xlsx'); $this->assertCount(1, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'password' => 'secret', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', 'password' => 'secret', ]); $this->assertEquals(2, User::count()); } public function test_can_upsert_models_in_rows() { User::create([ 'name' => 'Funny Potato', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithUpserts { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return string|array */ public function uniqueBy() { return 'email'; } }; $import->import('import-users.xlsx'); $this->assertCount(2, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'password' => 'secret', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', 'password' => 'secret', ]); $this->assertEquals(2, User::count()); } public function test_can_upsert_models_in_batches_with_defined_upsert_columns() { User::create([ 'name' => 'Funny Banana', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithBatchInserts, WithUpserts, WithUpsertColumns { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return string|array */ public function uniqueBy() { return 'email'; } /** * @return array */ public function upsertColumns() { return ['name']; } /** * @return int */ public function batchSize(): int { return 2; } }; $import->import('import-users.xlsx'); $this->assertCount(1, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', 'password' => 'secret', ]); $this->assertEquals(2, User::count()); } public function test_can_upsert_models_in_rows_with_defined_upsert_columns() { User::create([ 'name' => 'Funny Potato', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); DB::connection()->enableQueryLog(); $import = new class implements ToModel, WithUpserts, WithUpsertColumns { use Importable; /** * @param array $row * @return Model|Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return string|array */ public function uniqueBy() { return 'email'; } /** * @return array */ public function upsertColumns() { return ['name']; } }; $import->import('import-users.xlsx'); $this->assertCount(2, DB::getQueryLog()); DB::connection()->disableQueryLog(); $this->assertDatabaseHas('users', [ 'name' => 'Patrick Brouwers', 'email' => 'patrick@maatwebsite.nl', 'password' => 'password', ]); $this->assertDatabaseHas('users', [ 'name' => 'Taylor Otwell', 'email' => 'taylor@laravel.com', 'password' => 'secret', ]); $this->assertEquals(2, User::count()); } } ================================================ FILE: tests/Concerns/WithValidationTest.php ================================================ loadLaravelMigrations(['--database' => 'testing']); $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations'); } public function test_can_validate_rows() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The selected 1(field)? is invalid.', ]); $this->assertRegex( '/There was an error on row 2. The selected 1 (field)?is invalid./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_closure_validation_rules() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => function ($attribute, $value, $onFail) { if ($value !== 'patrick@maatwebsite.nl') { $onFail(sprintf('Value in column 1 is not an allowed e-mail.')); } }, ]; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'Value in column 1 is not an allowed e-mail.', ]); $this->assertRegex( '/There was an error on row 2. Value in column 1 is not an allowed e-mail./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_custom_validation_rule_objects() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => new class implements \Illuminate\Contracts\Validation\Rule { /** * @param string $attribute * @param mixed $value * @return bool */ public function passes($attribute, $value) { return $value === 'patrick@maatwebsite.nl'; } /** * Get the validation error message. * * @return string|array */ public function message() { return 'Value is not an allowed e-mail.'; } }, ]; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'Value is not an allowed e-mail.', ]); $this->assertRegex( '/There was an error on row 2. Value is not an allowed e-mail./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_conditionality() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ 'conditional_required_column' => 'required_if:1,patrick@maatwebsite.nl', ]; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 1, 'conditional_required_column', [ 'The conditional_required_column field is required when 1.1 is patrick@maatwebsite.nl.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_unless_conditionality() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ 'conditional_required_unless_column' => 'required_unless:1,patrick@maatwebsite.nl', ]; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, 'conditional_required_unless_column', [ 'The conditional_required_unless_column field is required unless 2.1 is in patrick@maatwebsite.nl.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_combined_rules_with_colons() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => 'required_with:0|unique:users,email', ]; } }; $import->import('import-users.xlsx'); $this->assertDatabaseHas('users', [ 'email' => 'patrick@maatwebsite.nl', ]); try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 1, '1', [ 'The 1 has already been taken.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_with_custom_attributes() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } /** * @return array */ public function customValidationAttributes() { return ['1' => 'email']; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, 'email', [ 'The selected email is invalid.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_with_custom_attributes_pointing_to_another_attribute() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => ['required'], '2' => ['required_with:*.1'], ]; } /** * @return array */ public function customValidationAttributes() { return ['1' => 'email', '2' => 'password']; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 1, 'password', [ 'The password field is required when email is present.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_with_custom_message() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => Rule::in(['patrick@maatwebsite.nl']), ]; } /** * @return array */ public function customValidationMessages() { return [ '1.in' => 'Custom message for :attribute.', ]; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'Custom message for 1.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_headings() { $import = new class implements ToModel, WithHeadingRow, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ 'email' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; try { $import->import('import-users-with-headings.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 3, 'email', [ 'The selected email is invalid.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_with_grouped_headings() { $import = new class implements ToModel, WithGroupedHeadingRow, WithValidation { use Importable; /** * Prepare the data for validation. * * @param array $row * @param int $index * @return array */ public function prepareForValidation(array $row, int $index) { if ($index === 2) { Assert::assertIsArray($row['options']); $row['options'] = 'not an array'; } return $row; } /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', 'options' => $row['options'], ]); } /** * @return array */ public function rules(): array { return [ 'options' => 'array', ]; } }; try { $import->import('import-users-with-grouped-headers.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, 'options', [ 'The options( field)? must be an array.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_rows_in_batches() { $import = new class implements ToModel, WithHeadingRow, WithBatchInserts, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => 'secret', ]); } /** * @return int */ public function batchSize(): int { return 2; } /** * @return array */ public function rules(): array { return [ 'email' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; try { $import->import('import-users-with-headings.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 3, 'email', [ 'The selected email is invalid.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_using_oneachrow() { $import = new class implements OnEachRow, WithHeadingRow, WithValidation { use Importable; /** * @param Row $row * @return Model|null */ public function onRow(Row $row) { $values = $row->toArray(); return new User([ 'name' => $values['name'], 'email' => $values['email'], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ 'email' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; try { $import->import('import-users-with-headings.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 3, 'email', [ 'The selected email is invalid.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_using_collection() { $import = new class implements ToCollection, WithHeadingRow, WithValidation { use Importable; public function collection(Collection $rows) { // } /** * @return array */ public function rules(): array { return [ 'email' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; try { $import->import('import-users-with-headings.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 3, 'email', [ 'The selected email is invalid.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_validate_using_array() { $import = new class implements ToArray, WithHeadingRow, WithValidation { use Importable; public function array(array $rows) { // } /** * @return array */ public function rules(): array { return [ 'email' => Rule::in(['patrick@maatwebsite.nl']), ]; } }; try { $import->import('import-users-with-headings.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 3, 'email', [ 'The selected email is invalid.', ]); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_configure_validator() { $import = new class implements ToModel, WithValidation { use Importable; /** * @param array $row * @return Model|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return array */ public function rules(): array { return [ '1' => 'email', ]; } /** * Configure the validator. * * @param \Illuminate\Contracts\Validation\Validator $validator * @return void */ public function withValidator($validator) { $validator->sometimes('*.1', Rule::in(['patrick@maatwebsite.nl']), function () { return true; }); } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The selected 1 is invalid.', ]); $this->assertRegex( '/There was an error on row 2. The selected 1 (field)?is invalid./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_prepare_using_toarray() { $import = new class implements ToArray, WithValidation { use Importable; /** * @return array */ public function rules(): array { return [ '1' => 'email', ]; } /** * Prepare the data for validation. * * @param array $row * @param int $index * @return array */ public function prepareForValidation(array $row, int $index) { if ($index === 2) { $row[1] = 'not an email'; } return $row; } /** * @param array $array * @return array */ public function array(array $array) { return []; } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The 1( field)? must be a valid email address.', ]); $this->assertRegex( '/There was an error on row 2. The 1( field)? must be a valid email address./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_prepare_using_tocollection() { $import = new class implements ToCollection, WithValidation { use Importable; /** * @return array */ public function rules(): array { return [ '1' => 'email', ]; } /** * Prepare the data for validation. * * @param array $row * @param int $index * @return array */ public function prepareForValidation(array $row, int $index) { if ($index === 2) { $row[1] = 'not an email'; } return $row; } /** * @param \Illuminate\Support\Collection $collection * @return mixed */ public function collection(Collection $collection) { return collect(); } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The 1( field)? must be a valid email address.', ]); $this->assertRegex( '/There was an error on row 2. The 1( field)? must be a valid email address./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_prepare_using_tomodel() { $import = new class implements ToModel, WithValidation { use Importable; /** * @return array */ public function rules(): array { return [ '1' => 'email', ]; } /** * Prepare the data for validation. * * @param array $row * @param int $index * @return array */ public function prepareForValidation(array $row, int $index) { if ($index === 2) { $row[1] = 'not an email'; } return $row; } /** * @param array $row * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Model[]|null */ public function model(array $row) { return new User([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The 1( field)? must be a valid email address.', ]); $this->assertRegex( '/There was an error on row 2. The 1( field)? must be a valid email address./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_prepare_using_oneachrow() { $import = new class implements OnEachRow, WithValidation { use Importable; /** * @return array */ public function rules(): array { return [ '1' => 'email', ]; } /** * Prepare the data for validation. * * @param array $row * @param int $index * @return array */ public function prepareForValidation(array $row, int $index) { if ($index === 2) { $row[1] = 'not an email'; } return $row; } /** * @param \Maatwebsite\Excel\Row $row * @return void */ public function onRow(Row $row) { User::query()->create([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The 1( field)? must be a valid email address.', ]); $this->assertRegex( '/There was an error on row 2. The 1( field)? must be a valid email address./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } public function test_can_prepare_using_skipsemptyrows() { $import = new class implements OnEachRow, WithValidation, SkipsEmptyRows { use Importable; /** * @return array */ public function rules(): array { return [ '1' => 'email', ]; } /** * Prepare the data for validation. * * @param array $row * @param int $index * @return array */ public function prepareForValidation(array $row, int $index) { if ($index === 2) { $row[1] = 'not an email'; } return $row; } /** * @param \Maatwebsite\Excel\Row $row * @return void */ public function onRow(Row $row) { User::query()->create([ 'name' => $row[0], 'email' => $row[1], 'password' => 'secret', ]); } }; try { $import->import('import-users.xlsx'); } catch (ValidationException $e) { $this->validateFailure($e, 2, '1', [ 'The 1( field)? must be a valid email address.', ]); $this->assertRegex( '/There was an error on row 2. The 1( field)? must be a valid email address./', $e->errors()[0][0] ); } $this->assertInstanceOf(ValidationException::class, $e ?? null); } /** * @param ValidationException $e * @param int $row * @param string $attribute * @param array $messages */ private function validateFailure(ValidationException $e, int $row, string $attribute, array $messages) { $failures = $e->failures(); $failure = head($failures); $this->assertEquals($row, $failure->row()); $this->assertEquals($attribute, $failure->attribute()); $this->assertEquals($row, $failure->jsonSerialize()['row']); $this->assertEquals($attribute, $failure->jsonSerialize()['attribute']); $this->assertRegex('/' . $messages[0] . '/', $failure->errors()[0]); $this->assertRegex('/' . $messages[0] . '/', $failure->jsonSerialize()['errors'][0]); } } ================================================ FILE: tests/Data/Disks/.gitignore ================================================ * !.gitignore !Local/ !Test/ ================================================ FILE: tests/Data/Stubs/AfterQueueExportJob.php ================================================ filePath = $filePath; } public function handle() { TestCase::assertFileExists($this->filePath); } } ================================================ FILE: tests/Data/Stubs/AfterQueueImportJob.php ================================================ totalRows = $totalRows; } public function handle() { Assert::assertEquals($this->totalRows, DB::table('groups')->count('id')); } } ================================================ FILE: tests/Data/Stubs/BeforeExportListener.php ================================================ assertions = $assertions; } public function __invoke() { ($this->assertions)(...func_get_args()); } } ================================================ FILE: tests/Data/Stubs/ChainedJobStub.php ================================================ define(Group::class, function (Faker $faker) { return [ 'name' => $faker->word, ]; }); ================================================ FILE: tests/Data/Stubs/Database/Factories/UserFactory.php ================================================ define(User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret 'remember_token' => Str::random(10), ]; }); ================================================ FILE: tests/Data/Stubs/Database/Group.php ================================================ belongsToMany(User::class); } } ================================================ FILE: tests/Data/Stubs/Database/Migrations/0000_00_00_000000_create_groups_table.php ================================================ increments('id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down() { Schema::dropIfExists('groups'); } } ================================================ FILE: tests/Data/Stubs/Database/Migrations/0000_00_00_000001_create_group_user_table.php ================================================ increments('id'); $table->unsignedInteger('group_id')->index(); $table->unsignedInteger('user_id')->index(); }); } /** * Reverse the migrations. */ public function down() { Schema::dropIfExists('group_user'); } } ================================================ FILE: tests/Data/Stubs/Database/Migrations/0000_00_00_000002_add_group_id_to_users_table.php ================================================ unsignedInteger('group_id')->index()->nullable(); }); } /** * Reverse the migrations. */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('group_id'); }); } } ================================================ FILE: tests/Data/Stubs/Database/Migrations/0000_00_00_000002_add_options_to_users.php ================================================ text('options')->nullable(); }); } /** * Reverse the migrations. */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('options'); }); } } ================================================ FILE: tests/Data/Stubs/Database/User.php ================================================ 'array', ]; /** * @var array */ protected $hidden = ['password', 'email_verified_at', 'options', 'group_id']; public function groups(): BelongsToMany { return $this->belongsToMany(Group::class); } public function group(): BelongsTo { return $this->belongsTo(Group::class); } /** * Laravel Scout under <=8 provides only * — NullEngine, that is searches nothing and not applicable for tests and * — AlgoliaEngine, that is 3-d party dependent and not applicable for tests too. * * The only test-ready engine is DatabaseEngine that comes with Scout >8 * * Then running tests we will examine engine and skip test until DatabaseEngine is provided. * * @see QueuedQueryExportTest::can_queue_scout_export() * @see FromQueryTest::can_export_from_scout() */ public function searchableUsing(): Engine { return class_exists('\Laravel\Scout\Engines\DatabaseEngine') ? new DatabaseEngine() : new NullEngine(); } } ================================================ FILE: tests/Data/Stubs/EloquentCollectionWithMappingExport.php ================================================ 'Patrick', 'lastname' => 'Brouwers', ]), ]); } /** * @param User $user * @return array */ public function map($user): array { return [ $user->firstname, $user->lastname, ]; } } ================================================ FILE: tests/Data/Stubs/EloquentLazyCollectionExport.php ================================================ 'Patrick', 'lastname' => 'Brouwers', ], [ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ], [ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ], [ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ], ])->lazy(); } } ================================================ FILE: tests/Data/Stubs/EloquentLazyCollectionQueuedExport.php ================================================ 'Patrick', 'lastname' => 'Brouwers', ], [ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ], [ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ], [ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ], ])->lazy(); } } ================================================ FILE: tests/Data/Stubs/EmptyExport.php ================================================ $this->beforeExport ?? function () { }, BeforeWriting::class => $this->beforeWriting ?? function () { }, BeforeSheet::class => $this->beforeSheet ?? function () { }, AfterSheet::class => $this->afterSheet ?? function () { }, ]; } } ================================================ FILE: tests/Data/Stubs/ExportWithEventsChunks.php ================================================ function (AfterChunk $event) { ExportWithEventsChunks::$calledEvent++; Assert::assertInstanceOf(ExportWithEventsChunks::class, $event->getConcernable()); }, ]; } public function query(): Builder { return User::query(); } public function chunkSize(): int { return 1; } } ================================================ FILE: tests/Data/Stubs/ExportWithRegistersEventListeners.php ================================================ users(); } /** * @param mixed $row * @return array */ public function map($row): array { return [ $row->name, $row->email, ]; } /** * @return int */ public function chunkSize(): int { return 10; } } ================================================ FILE: tests/Data/Stubs/FromNestedArraysQueryExport.php ================================================ name, '']; $count = 0; foreach ($row->users as $user) { if ($count === 0) { $sub_row[1] = $user['email']; } else { $sub_row = ['', $user['email']]; } $rows[] = $sub_row; $count++; } if ($count === 0) { $rows[] = $sub_row; } return $rows; } } ================================================ FILE: tests/Data/Stubs/FromNonEloquentQueryExport.php ================================================ select('name')->orderBy('id'); } /** * @return int */ public function chunkSize(): int { return 10; } } ================================================ FILE: tests/Data/Stubs/FromQueryWithCustomQuerySize.php ================================================ join('group_user', 'groups.id', '=', 'group_user.group_id') ->select('groups.*', DB::raw('count(group_user.user_id) as number_of_users')) ->groupBy('groups.id') ->orderBy('number_of_users'); return $query; } /** * @return int */ public function querySize(): int { return Group::has('users')->count(); } /** * @param Group $row * @return array */ public function map($row): array { return [ $row->id, $row->name, $row->number_of_users, ]; } } ================================================ FILE: tests/Data/Stubs/FromUsersQueryExport.php ================================================ with([ 'groups' => function ($query) { $query->where('name', 'Group 1'); }, ])->withCount('groups'); } /** * @param mixed $row * @return array */ public function map($row): array { return [ $row->name, $row->groups_count, $row->groups->implode('name', ', '), ]; } } ================================================ FILE: tests/Data/Stubs/FromUsersQueryExportWithMapping.php ================================================ function (BeforeSheet $event) { $event->sheet->chunkSize(10); }, ]; } /** * @param User $row * @return array */ public function map($row): array { return [ 'name' => $row->name, ]; } } ================================================ FILE: tests/Data/Stubs/FromUsersQueryExportWithPrepareRows.php ================================================ map(function ($user) { $user->name .= '_prepared_name'; return $user; })->toArray(); } } ================================================ FILE: tests/Data/Stubs/FromUsersQueryWithJoinExport.php ================================================ query = User::query(); } /** * @return Builder|EloquentBuilder|Relation */ public function query() { return $this->query ->join( 'group_user', 'group_user.user_id', '=', 'users.id' ) ->select('users.*', 'group_user.group_id as gid'); } /** * @return int */ public function chunkSize(): int { return 10; } } ================================================ FILE: tests/Data/Stubs/FromUsersScoutExport.php ================================================ users = $users; } /** * @return SheetForUsersFromView[] */ public function sheets(): array { return [ new SheetForUsersFromView($this->users->forPage(1, 100)), new SheetForUsersFromView($this->users->forPage(2, 100)), new SheetForUsersFromView($this->users->forPage(3, 100)), ]; } } ================================================ FILE: tests/Data/Stubs/ImportWithEvents.php ================================================ $this->beforeImport ?? function () { }, AfterImport::class => $this->afterImport ?? function () { }, BeforeSheet::class => $this->beforeSheet ?? function () { }, AfterSheet::class => $this->afterSheet ?? function () { }, ]; } } ================================================ FILE: tests/Data/Stubs/ImportWithEventsChunksAndBatches.php ================================================ $this->afterBatch ?? function () { }, AfterChunk::class => $this->afterChunk ?? function () { }, ]; } public function model(array $row) { } public function batchSize(): int { return 100; } public function chunkSize(): int { return 500; } } ================================================ FILE: tests/Data/Stubs/ImportWithRegistersEventListeners.php ================================================ $row[0], 'email' => $row[1], 'password' => 'secret', ]); } /** * @return int */ public function chunkSize(): int { return 1; } /** * @return array */ public function registerEvents(): array { return [ BeforeImport::class => function (BeforeImport $event) { Assert::assertInstanceOf(Reader::class, $event->reader); $this->before = true; }, AfterImport::class => function (AfterImport $event) { Assert::assertInstanceOf(Reader::class, $event->reader); $this->after = true; }, ]; } } ================================================ FILE: tests/Data/Stubs/QueuedExport.php ================================================ getMessage()); app()->bind('queue-has-failed-from-queue-export-job', function () { return true; }); } /** * @return array */ public function registerEvents(): array { return [ BeforeExport::class => function () { throw new Exception('catch exception from QueueExport job'); }, ]; } } ================================================ FILE: tests/Data/Stubs/QueuedExportWithFailedHook.php ================================================ 'Patrick', 'lastname' => 'Brouwers', ]), ]); } /** * @param User $user * @return array */ public function map($user): array { throw new Exception('we expect this'); } /** * @param Exception $exception */ public function failed(Exception $exception) { Assert::assertEquals('we expect this', $exception->getMessage()); app()->bind('queue-has-failed', function () { return true; }); } } ================================================ FILE: tests/Data/Stubs/QueuedExportWithLocalePreferences.php ================================================ locale = $locale; } /** * @return Collection */ public function collection() { return collect([ new User([ 'firstname' => 'Patrick', 'lastname' => 'Brouwers', ]), ]); } /** * @return string|null */ public function preferredLocale() { return $this->locale; } /** * @param iterable $rows * @return iterable */ public function prepareRows($rows) { Assert::assertEquals('ru', app()->getLocale()); app()->bind('queue-has-correct-locale', function () { return true; }); return $rows; } } ================================================ FILE: tests/Data/Stubs/QueuedImport.php ================================================ $row[0], ]); } /** * @return int */ public function batchSize(): int { return 100; } /** * @return int */ public function chunkSize(): int { return 100; } } ================================================ FILE: tests/Data/Stubs/QueuedImportWithFailure.php ================================================ $row[0], ]); } /** * @return int */ public function chunkSize(): int { return 100; } } ================================================ FILE: tests/Data/Stubs/QueuedImportWithMiddleware.php ================================================ $row[0], ]); } public function middleware() { return [function () { throw new \Exception('Job reached middleware method'); }]; } /** * @return int */ public function chunkSize(): int { return 100; } } ================================================ FILE: tests/Data/Stubs/QueuedImportWithRetryUntil.php ================================================ $row[0], ]); } /** * @return int */ public function chunkSize(): int { return 100; } /** * Determine the time at which the job should timeout. * * @return \DateTime */ public function retryUntil() { throw new \Exception('Job reached retryUntil method'); return now()->addSeconds(5); } } ================================================ FILE: tests/Data/Stubs/SheetForUsersFromView.php ================================================ users = $users; } /** * @return View */ public function view(): View { return view('users', [ 'users' => $this->users, ]); } } ================================================ FILE: tests/Data/Stubs/SheetWith100Rows.php ================================================ title = $title; } /** * @return Collection */ public function collection() { $collection = new Collection; for ($i = 0; $i < 100; $i++) { $row = new Collection(); for ($j = 0; $j < 5; $j++) { $row[] = $this->title() . '-' . $i . '-' . $j; } $collection->push($row); } return $collection; } /** * @return string */ public function title(): string { return $this->title; } /** * @param BeforeWriting $event */ public static function beforeWriting(BeforeWriting $event) { TestCase::assertInstanceOf(Writer::class, $event->writer); } } ================================================ FILE: tests/Data/Stubs/ShouldQueueExport.php ================================================